Taogen's Blog

Stay hungry stay foolish.

Gotenberg is a great open source project for converting files to PDF.

Starting Up Gotenberg

docker run --rm -p 3000:3000 gotenberg/gotenberg:7
# Run container in background
docker run --rm -d -p 3000:3000 gotenberg/gotenberg:7

View console output of Gotenberg

docker container ls
docker logs -f <containerId>

API Usage

Health Check

http://localhost:3000/health

Chromium

The Chromium module interacts with the Chromium browser to convert HTML documents to PDF.

Converting HTML URLs to PDF

curl \
--request POST 'http://localhost:3000/forms/chromium/convert/url' \
--form 'url="https://my.url"' \
-o my.pdf

Converting local HTML files to PDF

curl \
--request POST 'http://localhost:3000/forms/chromium/convert/html' \
--form 'files=@"/file/path/to/index.html"' \
-o my.pdf

LibreOffice

The LibreOffice module interacts with LibreOffice to convert documents to PDF.

To convert documents to PDF

Files with the following extensions:

.bib` `.doc` `.xml` `.docx` `.fodt` `.html` `.ltx` `.txt` `.odt` `.ott` `.pdb` `.pdf` `.psw` `.rtf` `.sdw` `.stw` `.sxw` `.uot` `.vor` `.wps` `.epub` `.png` `.bmp` `.emf` `.eps` `.fodg` `.gif` `.jpg` `.met` `.odd` `.otg` `.pbm` `.pct` `.pgm` `.ppm` `.ras` `.std` `.svg` `.svm` `.swf` `.sxd` `.sxw` `.tiff` `.xhtml` `.xpm` `.fodp` `.potm` `.pot` `.pptx` `.pps` `.ppt` `.pwp` `.sda` `.sdd` `.sti` `.sxi` `.uop` `.wmf` `.csv` `.dbf` `.dif` `.fods` `.ods` `.ots` `.pxl` `.sdc` `.slk` `.stc` `.sxc` `.uos` `.xls` `.xlt` `.xlsx` `.tif` `.jpeg` `.odp

Converting local document files to PDF

Relative file path

curl \
--request POST 'http://localhost:3000/forms/libreoffice/convert' \
--form 'files=@"test.docx"' \
-o test.pdf

Absolute file path

curl \
--request POST 'http://localhost:3000/forms/libreoffice/convert' \
--form 'files=@"D:\My Workspace\test.docx"' \
-o test.pdf

Multiple files

curl \
--request POST 'http://localhost:3000/forms/libreoffice/convert' \
--form 'files=@"/path/to/file.docx"' \
--form 'files=@"/path/to/file.xlsx"' \
-o my.zip

Request by Java OkHttp

private static final String GOTENBERG_SERVICE_HOST = "http://xxx.xxx.xxx.xxx:3000";

private static final String CONVERT_TO_PDF_URI = "/forms/libreoffice/convert";

private static final OkHttpClient OKHTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();

public static byte[] convertToPdfByGotenberg(InputStream inputStream, String fileName) throws IOException {
Request.Builder requestBuilder = new Request.Builder()
.url(HttpUrl.parse(GOTENBERG_SERVICE_HOST + CONVERT_TO_PDF_URI).newBuilder().build());
String mediaType = URLConnection.guessContentTypeFromName(fileName);
if (mediaType == null) {
mediaType = "application/octet-stream";
}
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("files", fileName,
RequestBody.create(MediaType.parse(mediaType),
IOUtils.toByteArray(inputStream)));
requestBuilder.post(builder.build());
try (Response response = OKHTTP_CLIENT.newCall(requestBuilder.build()).execute()) {
return response.body().bytes();
}
}

PDF Engines

Merge multiple PDF files to one PDF file.

curl \
--request POST 'http://localhost:3000/forms/pdfengines/merge' \
--form 'files=@"/path/to/pdf1.pdf"' \
--form 'files=@"/path/to/pdf2.pdf"' \
--form 'files=@"/path/to/pdf3.pdf"' \
--form 'files=@"/path/to/pdf4.pdf"' \
-o my.pdf

Webhook

The Webhook module provides a middleware that allows you to upload the output file from multipart/form-data routes to the destination of your choice.

curl \
--request POST 'http://localhost:3000/forms/chromium/convert/url' \
--header 'Gotenberg-Webhook-Extra-Http-Headers: {"MyHeader": "MyValue"}' \
--header 'Gotenberg-Webhook-Url: https://my.webhook.url' \
--header 'Gotenberg-Webhook-Method: PUT' \
--header 'Gotenberg-Webhook-Error-Url: https://my.webhook.error.url' \
--header 'Gotenberg-Webhook-Error-Method: POST' \
--form 'url="https://my.url"'

The middleware reads the following headers:

  • Gotenberg-Webhook-Url - the callback to use - required
  • Gotenberg-Webhook-Error-Url - the callback to use if error - required
  • Gotenberg-Webhook-Method - the HTTP method to use (POST, PATCH, or PUT - default POST).
  • Gotenberg-Webhook-Error-Method - the HTTP method to use if error (POST, PATCH, or PUT - default POST).
  • Gotenberg-Webhook-Extra-Http-Headers - the extra HTTP headers to send to both URLs (JSON format).

Common Errors

Error: file name is too long

{"level":"error","ts":1649232587.172472,"logger":"api","msg":"create request context: copy to disk: create local file: open /tmp/9e10e36d-c5a9-4623-9fac-92db4a0d0982/xxx.doc: file name too long","trace":"de0b5ce2-5a99-406e-a61d-4abb65ef0294","remote_ip":"xxx.xxx.xxx.xxx","host":"xxx.xxx.xxx.xxx:3000","uri":"/forms/libreoffice/convert","method":"POST","path":"/forms/libreoffice/convert","referer":"","user_agent":"okhttp/4.9.3","status":500,"latency":13161094736,"latency_human":"13.161094736s","bytes_in":6983097,"bytes_out":21}

Solutions

Decreasing your file name length.

Error: file name contains UTF-8 characters

{"level":"error","ts":1649234692.9638329,"logger":"api","msg":"convert to PDF: unoconv PDF: unix process error: wait for unix process: exit status 6","trace":"28d9a196-10e5-4c7d-af6a-178494f49cd1","remote_ip":"xxx.xxx.xxx.xxx","host":"xxx.xxx.xxx.xxx:3000","uri":"/forms/libreoffice/convert","method":"POST","path":"/forms/libreoffice/convert","referer":"","user_agent":"okhttp/4.9.3","status":500,"latency":130617774,"latency_human":"130.617774ms","bytes_in":11559,"bytes_out":21}

Solutions

Encoding filename by URLEncoder.encode(fileName, "UTF-8").

Error: file extension name is not right

{"level":"error","ts":1649234777.9096093,"logger":"api","msg":"validate form data: no form file found for extensions: [.bib .doc .xml .docx .fodt .html .ltx .txt .odt .ott .pdb .pdf .psw .rtf .sdw .stw .sxw .uot .vor .wps .epub .png .bmp .emf .eps .fodg .gif .jpg .jpeg .met .odd .otg .pbm .pct .pgm .ppm .ras .std .svg .svm .swf .sxd .sxw .tif .tiff .xhtml .xpm .odp .fodp .potm .pot .pptx .pps .ppt .pwp .sda .sdd .sti .sxi .uop .wmf .csv .dbf .dif .fods .ods .ots .pxl .sdc .slk .stc .sxc .uos .xls .xlt .xlsx]","trace":"10e6ffd8-2d00-4374-b6fb-0c4ff6af3043","remote_ip":"xxx.xxx.xxx.xxx","host":"xxx.xxx.xxx.xxx:3000","uri":"/forms/libreoffice/convert","method":"POST","path":"/forms/libreoffice/convert","referer":"","user_agent":"okhttp/4.9.3","status":400,"latency":3885166,"latency_human":"3.885166ms","bytes_in":11551,"bytes_out":449}

Solutions

Files in form data should have a correct file extension.

References

Gotenberg Documentation

To get a good job, to become a good developer first.

Keep Learning

  • Reading textbooks, documentation.
  • Reading open-source code.
  • Writing blogs.

Practice Your Craft

  • Design yourself systems.
  • Build yourself systems.
  • Optimizes systems.
  • Solving coding problems on LeetCode.

Build Your Reputations

  • Contributing to open-source projects on GitHub.
  • Answering questions on Stack Overflow.
  • Keep writing technical blogs on your website.

What is Empty Cache and Hard Reload for Specific Domain

Clear current domain website cached static files, like HTML, CSS, JS, and images files.

Note: “Hard reload” is only clear current page cached static files not current domain. For current domain we need use “Empty Cache and Hard Reload”

Empty Cache and Hard Reload

Chrome

Method One

  1. Press control+shift+I or F12 to open Chrome Developer Tools.
  2. Right-click the reload button next to the address bar.
  3. Choose: “Empty Cache and Hard Reload”.

Method Two

  1. Press control+shift+I or F12 to open Chrome Developer Tools.
  2. Under Network (previously General) check Disable cache. (re-enable caching by un-checking this box)
  3. Reload the page.

Solution 1: Setting Proxy

First, use a US proxy instead of others, like HK.

Setting HTTP Proxy for git clone by HTTPS URL

setting HTTP proxy for git

git config --global http.proxy socks5h://127.0.0.1:1080
# or just proxy GitHub
git config --global http.https://github.com.proxy socks5h://127.0.0.1:1080

or temporarily setting HTTP proxy for your terminal

// linux
export ALL_PROXY=socks5://127.0.0.1:1080
// windows
set ALL_PROXY=socks5://127.0.0.1:1080

Test Case

Before Setting Proxy: about 200 KiB/s.

git clone https://github.com/mybatis/mybatis-3.git mybatis-clone-test
Cloning into 'mybatis-clone-test'...
remote: Enumerating objects: 397085, done.
remote: Counting objects: 100% (195/195), done.
remote: Compressing objects: 100% (79/79), done.
Receiving objects: 4% (15884/397085), 5.25 MiB | 197.00 KiB/s

After Setting Proxy: about 3 MiB/s.

git clone https://github.com/mybatis/mybatis-3.git mybatis-clone-test
Cloning into 'mybatis-clone-test'...
remote: Enumerating objects: 397085, done.
remote: Counting objects: 100% (195/195), done.
remote: Compressing objects: 100% (79/79), done.
Receiving objects: 14% (55592/397085), 18.63 MiB | 3.16 MiB/s

Proxy types

or Setting SSH Proxy for git clone by SSH URL

On Windows, add the following content to your git SSH config file ~/.ssh/config:

ProxyCommand "C:\Program Files\Git\mingw64\bin\connect.exe" -S 127.0.0.1:1080 %h %p

Host github.com
User git
Port 22
Hostname github.com
IdentityFile "C:\Users\Taogen\.ssh\id_ed25519"
TCPKeepAlive yes
IdentitiesOnly yes

Host ssh.github.com
User git
Port 443
Hostname ssh.github.com
IdentityFile "C:\Users\Taogen\.ssh\id_ed25519"
TCPKeepAlive yes
IdentitiesOnly yes

You can put the ProxyCommand ... under a specific Host xxx.xxx.xxx like this if you need to access multiple git hosting sites but set an SSH proxy for only one site.

Host ssh.github.com
ProxyCommand "C:\Program Files\Git\mingw64\bin\connect.exe" -S 127.0.0.1:1080 %h %p
...

Git SSH config file path

  • Windows:
    • per user SSH configuration file: ~/.ssh/config
    • system SSH configuration file: C:\ProgramData\ssh\ssh_config
  • Linux:
    • per user SSH configuration file: ~/.ssh/config
    • system SSH configuration file: /etc/ssh/ssh_config

Git connect program

  • Windows: {git_install_path}\Git\mingw64\bin\connect.exe (You can get the file path by running the command line where connect.exe)
  • Linux: /usr/bin/nc (You can get the file path by running the command line whereis nc)

Solution 2: Switching from using SSH to HTTPS

Using SSH: about 20 KiB/s

git clone git@github.com:xxx/xxx.git
Receiving objects: 0% (309/396867), 172.01 KiB | 26.00 KiB/s

Using HTTPS: about 400 KiB/s

git clone https://github.com/xxx/xxx.git
Receiving objects: 100% (396867/396867), 113.49 MiB | 402.00 KiB/s, done.

Other Improvements

git config --global http.postbuffer 524288000
git config --global credential.helper "cache --timeout=86400"

References

[1] GitHub 加速终极教程

[2] SSH in git behind proxy on windows 7

[3] ssh_config - OpenBSD

[4] nc - OpenBSD

Running the project

How to configure your local environment to run the project.

How the project was designed

Business Architecture Design

  • Business Process
  • System Function Structure

Application(System) Architecture Design

Type: Monolithic, Distributed, SOA

Division

  • Horizontal division: frontend, middle server, backend server.

  • Vertical division: subsystems.

Technical Architecture Design

Technology Stack

Techniques of every layer.

Layers: Persistence layer, data layer, logic layer, application layer, view layer.

Database Design

Interface Design

Implementation of Core Functions

Data Access

Data Source configuration, encapsulation, use

Redis configuration, encapsulation, use

Elasticsearch configuration, encapsulation, use

System Core Functions

User, role, privilege, and menu

Login authentication and authorization

Exception Handler

Logging

File upload and download

Data import and export

Scheduling Tasks

i18n

Code generation

A Module’s CRUD Function Implementation

How to Develop

Git Management

Project File Structure

The process of developing a module

Development Specification

Developing a New Module

Create a database table.

Write module source code.

Running project.

Test module functions.

Java

Constants

java.lang.Math

  • E
  • PI

java.net.HttpURLConnection

  • HTTP_OK
  • HTTP_NO_CONTENT
  • HTTP_BAD_REQUEST
  • HTTP_UNAUTHORIZED
  • HTTP_FORBIDDEN
  • HTTP_NOT_FOUND
  • HTTP_BAD_METHOD
  • HTTP_INTERNAL_ERROR

javax.management.timer.Timer

  • ONE_DAY
  • ONE_HOUR
  • ONE_MINUTE
  • ONE_SECOND
  • ONE_WEEK

Enum

java.nio.charset.StandardCharsets

  • ISO_8859_1
  • UTF_8.toString()

Utilities

java.util

  • Arrays
    • asList(T… a)
    • sort(int[] a)
    • toString(Object[] a)
  • Collections
    • emptyList()
    • emptyMap()
    • emptySet()
    • sort(List list)
    • sort(List list, Comparator<? super T> c)
  • Objects
    • nonNull()
    • isNull(Object obj)
    • equals(Object a, Object b)
    • deepEquals(Object a, Object b)
    • compare(T a, T b, Comparator<? super T> c)
    • requireNonNull(T obj, String message)
    • toString(Object o, String nullDefault)
  • UUID
    • randomUUID()

Others

  • Optional
  • Random
  • StringJoiner

Java Servlet

Constants

jakarta.servlet.http.HttpServletResponse

  • SC_OK
  • SC_CREATED
  • SC_NO_CONTENT
  • SC_BAD_REQUEST
  • SC_UNAUTHORIZED
  • SC_FORBIDDEN
  • SC_NOT_FOUND
  • SC_INTERNAL_SERVER_ERROR

Spring Framework

Constants

org.springframework.http.HttpHeaders

  • ACCEPT_LANGUAGE
  • AUTHORIZATION
  • CACHE_CONTROL
  • CONTENT_DISPOSITION
  • CONTENT_TYPE
  • USER_AGENT

org.springframework.http.MediaType

  • APPLICATION_JSON_VALUE
  • APPLICATION_FORM_URLENCODED_VALUE
  • MULTIPART_FORM_DATA_VALUE

Enum

org.springframework.http.HttpMethod

  • GET.toString()
  • POST
  • PUT
  • DELETE

org.springframework.http.HttpStatus

  • OK
  • NO_CONTENT
  • BAD_REQUEST
  • UNAUTHORIZED
  • FORBIDDEN
  • NOT_FOUND
  • METHOD_NOT_ALLOWED
  • INTERNAL_SERVER_ERROR

Utilities

org.springframework.util

  • StringUtils
    • hasLength(String str)
  • CollectionUtils
    • isEmpty(Collection<?> collection)
  • ClassUtils

org.springframework.beans

  • BeanUtils
    • copyProperties(Object source, Object target)

References

[1] Spring Framework Constant Field Values

[2] Java 8 Constant Field Values

企业微信应用介绍

企业微信应用开发是借助企业微信提供的API,开发针对企业微信平台的应用。企业微信用户可以通过企业微信客户端提供的企业微信应用入口来找到应用。企业微信客户端有 iOS,Android,Windows 等版本,用户可以在多个端同时使用。

企业微信应用按照API接口类型分为:

  • 企业内部应用。仅应用开发的企业内部微信用户可以使用的应用。
  • 第三方应用。所有企业的微信用户可以使用的应用。该应用在企业微信第三方应用市场可以找到。
  • 智慧软硬件应用。面向智能硬件厂商,基于企业微信提供的硬件SDK,升级硬件能力,并提供软硬一体的场景化方案。所有企业的微信用户可以使用的应用。该应用在企业微信第三方应用市场可以找到。

这三种应用的大部分API是相同的,小部分API不同或者仅某种应用可以使用。

按照应用场景分为:

  • H5应用。网页类型的应用。
  • 小程序应用。
  • 群聊机器人。通过机器人,企业应用可以主动向群聊内发送多种类型的消息。
  • 管理和辅助类型应用。

企业微信应用的基本使用:

  1. 企业微信H5应用(微信用户主动使用该应用)。微信用户在企业微信客户端找到应用入口,进入应用的首页,企业微信用户使用应用页面上的功能。
  2. 管理和辅助类型应用(非微信用户使用或被动使用应用)。如通讯录管理、消息推送等。应用的管理后台主动触发相关功能。

企业微信应用开发

企业微信应用涉及的交互:

  • 企业微信客户端调用应用服务器的API
  • 应用服务器调用企业微信的API
  • 企业微信回调应用服务器API。

企业内部应用(自建应用)开发流程

  1. 注册企业微信。获取 corpId (Company ID)。
  2. 创建应用。登录企业微信管理后台,在应用管理中创建自建应用。上传 App Logo 和输入 App Name。得到 AgentId 和 Secret。
  3. 配置应用(非 H5 应用不需要配置)。企业微信管理后台的应用详情页面,1)配置应用主页,2)设置可信域名。
  4. 开发应用。通过调用企业微信服务端 API 实现相关业务功能。
  5. 将企业微信应用部署到自己的服务器。

Appendixes

HTML pages referred static files (images, js and css etc) can be cached in your browser by setting HTTP response header attributes about cache.

Two main types of cache headers, cache-control and expires, define the caching characteristics for your resources. Typically, cache-control is considered a more modern and flexible approach than expires, but both headers can be used simultaneously.

Cache headers are applied to resources at the server level – for example, in the .htaccess file on an Apache server, used by nearly half of all active websites – to set their caching characteristics. Caching is enabled by identifying a resource or type of resource, such as images or CSS files, and then specifying headers for the resource(s) with the desired caching options.

Stop using (HTTP 1.0) Replaced with (HTTP 1.1 since 1999)
Expires: [date] Cache-Control: max-age=[seconds]
Pragma: no-cache Cache-Control: no-cache

Setting HTTP cache in Spring framework

Setting HTTP response cache-control header in Spring framework

return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)
.cachePrivate()
.mustRevalidate())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + fileName + "\"")
.body(resource);

Setting HTTP cache in Nginx Server

Only set HTTP Cache-Control header for HTTP directly response by Nginx, not proxy_pass server HTTP responses. In other words, request static files via the server’s file path. For example:

  • expires 30d;
  • add_header Cache-Control “public, no-transform”;

conf/nginx.conf

server {
listen 80;
server_name localhost;
location / {
autoindex on;
root html;
index index.html index.htm;
}
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
root /root/upload
expires 30d;
add_header Cache-Control "public, no-transform";
}
}

Cache-Control Directives

Cache

  • Cache types: private / public
  • Expired time: max-age / s-maxage
  • validated-related:
    • no-cache
    • must-revalidate/proxy-revalidate: Indicates that once a resource becomes stale, caches must not use their stale copy without successful validation on the origin server.
    • stale-while-revalidate
    • stale-if-error
    • no-transform
    • immutable: Indicates that the response body will not change over time. The resource, if unexpired, is unchanged on the server and therefore the client should not send a conditional revalidation for it.

Examples:

Cache-Control: public, max-age=604800, must-revalidate

No Cache

  • no-store or max-age=0

Note that no-cache does not mean “don’t cache”. no-cache allows caches to store a response but requires them to revalidate it before reuse. If the sense of “don’t cache” that you want is actually “don’t store”, then no-store is the directive to use.

Examples

Cache-Control: no-store

Cache-Control Directive Details

Max Age for Files

  • ico/jpg/jpeg/png/gif: max-age=2592000 seconds (30 days) or max-age=31536000 (365 days)
  • pdf: max-age=2592000 seconds (30 days)
  • css/js: max-age=86400 seconds (1 hours) or max-age=2592000 seconds (30 days)

References

Elements

View Event Listeners of HTML Elements

Element -> Event Listeners

  • Ancestors: unchecked
  • All/Passive/Blocking: Blocking
  • Framework listeners: checked

Edit HTML element

You can edit HTML on the fly and preview the changes by selecting any element, choosing a DOM element within the panel, and double clicking on the opening tag to edit it.

Edit CSS property

you can also change CSS in Chrome DevTools and preview what the result will look like. This is probably one of the most common uses for this tool. Simply select the element you want to edit and under the styles panel you can add/change any CSS property you want.

Change color format

You can toggle between RGBA, HSL, and hexadecimal formatting by pressing Shift + Click on the color block.

Console

Design Mode

you can freely make edits to the page as if it were a document.

Open design mode: document.designMode = “on”

Monitoring events on-page elements

monitorEvents($0, ‘mouse’)

Sources

Pretty print

You can easily change the formatting of your minimized code by clicking on {}.

Multiple cursors

You can easily add multiple cursors by pressing Cmd + Click (Ctrl + Click) and entering information on multiple lines at the same time.

Search source code

You can quickly search all of your source code by pressing Cmd + Opt + F (Ctrl + Shift + F).

Network

Without Cache When Access Web Page

Checked “Disable cache”

Others

Dock Position

You can also change the Chrome DevTools dock position. You can either undock into a separate window, or dock it on the left, bottom, or right side of the browser. The dock position can be changed by pressing Cmd + Shift + D (Ctrl + Shift + D) or through the menu.

References

[1] Chrome DevTools

[2] Chrome DevTools - 20+ Tips and Tricks

[3] 8 Lesser Known but KILLER Features of Chrome DevTools

Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order (with values from lower items overriding earlier ones):

  1. Default properties (specified by setting SpringApplication.setDefaultProperties).
  2. @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
  3. Config data (such as application.properties files).
    1. Application properties packaged inside your jar (application.properties and YAML variants).
    2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
    3. Application properties outside of your packaged jar (application.properties and YAML variants).
    4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
  4. A RandomValuePropertySource that has properties only in random.*.
  5. OS environment variables.
  6. Java System properties (System.getProperties()).
  7. JNDI attributes from java:comp/env.
  8. ServletContext init parameters.
  9. ServletConfig init parameters.
  10. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
  11. Command line arguments.
  12. properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
  13. @TestPropertySource annotations on your tests.
  14. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.

Config data

Specify a default configuration file

spring.config.location: specify a default configuration file path or directory

java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
mvn spring-boot:run -Dspring.config.location="file:///Users/home/jdbc.properties"
mvn spring-boot:run -Dspring.config.location="file:///D:/config/aliyun-oss-java/application.yml"
mvn spring-boot:run -Dspring.config.location="/Users/home/jdbc.properties"
mvn spring-boot:run -Dspring.config.location="D:/config/aliyun-oss-java/application.yml"

Importing Additional Configuration File

spring.config.additional-location: additional configuration file that will override default configuration file

Program arguments

java -jar your_app.jar --spring.config.additional-location=xxx

System Properties (VM Arguments)

java -jar -Dspring.config.additional-location=xxx your_app.jar

application.properties

spring.config.import=developer.properties

OS Environment Variables

If you add new OS Environment Variables on Windows, you must restart your processes (Java process, Intellij IDEA) to read the new OS Environment Variables.

For any other Windows executable, system-level changes to the environment variables are only propagated to the process when it is restarted.

Add User variables or System variables on Linux or Windows

msg=hello
  1. Read by System Class
System.getenv("msg")
  1. Read by Environment object
@Autowired
private Environment environment;

environment.getProperty("msg")
  1. Injecting environment variables
@Value("${msg}")
private String msg;
  1. Setting application.properties values from environment
msg=${msg}

JSON Application Properties

Environment variables and system properties often have restrictions that mean some property names cannot be used. To help with this, Spring Boot allows you to encode a block of properties into a single JSON structure.

When your application starts, any spring.application.json or SPRING_APPLICATION_JSON properties will be parsed and added to the Environment.

For example, the SPRING_APPLICATION_JSON property can be supplied on the command line in a UN*X shell as an environment variable:

$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar

In the preceding example, you end up with my.name=test in the Spring Environment.

The same JSON can also be provided as a system property:

$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar

Or you could supply the JSON by using a command line argument:

$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'

If you are deploying to a classic Application Server, you could also use a JNDI variable named java:comp/env/spring.application.json.

Accessing Command Line Properties

By default, SpringApplication converts any command line option arguments (that is, arguments starting with --, such as --server.port=9000) to a property and adds them to the Spring Environment. As mentioned previously, command line properties always take precedence over file-based property sources.

If you do not want command line properties to be added to the Environment, you can disable them by using SpringApplication.setAddCommandLineProperties(false).

Maven Command with application arguments:

mvn spring-boot:run -Dspring-boot.run.arguments="--arg1=value --arg2=value"
mvn spring-boot:run -D{arg.name}={value}
$ mvn spring-boot:run -Dspring-boot.run.arguments="--spring.profiles.active=production --server.port=8089"
$ mvn spring-boot:run -Dspring-boot.run.arguments="--spring.config.location=D:\config\aliyun-oss-java\application.yml"
# Spring-Boot 2.x
$ mvn spring-boot:run -Dspring-boot.run.profiles=local
# Spring-Boot 1.x and 2.x
$ mvn spring-boot:run -Dspring.profiles.active=local

java -jar with System Properties (VM Arguments = JVM flags + System Properties)

java -jar -D{arg.name}={value} {jar-file} // sometimes value need add quotes ""
$ mvn clean install spring-boot:repackage -Dmaven.test.skip=true
$ java -jar -Dspring.config.location="D:\config\aliyun-oss-java\application.yml" your_application.jar
$ java -jar -Dspring.profiles.active=prod your_application.jar

java -jar with Program Arguments

java -jar <jar-file> --{arg.name}={value} // sometimes value need add quotes ""
$ mvn clean install spring-boot:repackage -Dmaven.test.skip=true
$ java -jar your_application.jar --spring.config.location="D:\config\aliyun-oss-java\application.yml"

References

0%