Taogen's Blog

Stay hungry stay foolish.

Download

Downloading the Activiti UI WAR file from the Activiti website.

Unzip activiti-6.0.0.zip.

Copy the activiti-6.0.0/wars/activiti-app.war to the webapps directory of Tomcat.

Configuration

Updating configurations in activiti-app/WEB-INF/classes/META-INF/activiti-app/activiti-app.properties

datasource.driver=com.mysql.cj.jdbc.Driver
datasource.url=jdbc:mysql://127.0.0.1:3306/activiti6ui?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=GMT
datasource.username={your_username}
datasource.password={your_password}

hibernate.dialect=org.hibernate.dialect.MySQLDialect

Adding MySQL 8 driver mysql-connector-java-8.0.19.jar to lib directory activiti-app/WEB-INF/lib.

Initializing Database

Creating database activiti6ui that configuring in activiti-app/WEB-INF/classes/META-INF/activiti-app/activiti-app.properties.

Executing following Activiti initial SQL files:

  • activiti-6.0.0/database/create/activiti.mysql.create.engine.sql
  • activiti-6.0.0/database/create/activiti.mysql.create.history.sql
  • activiti-6.0.0/database/create/activiti.mysql.create.identity.sql

Running and Visiting

Start Tomcat by running the startup.bat or startup.sh scripts in the bin folder of Tomcat.

When Tomcat is started open your browser and go to http://localhost:8080/activiti-app. Login with admin and password test.

The Solution

  1. Using @Component inject the bean to the Spring IoC container.
  2. Using @Value read application configurations of Spring into non-static fields.
  3. Implements InitializingBean override afterPropertiesSet() method. Assigning non-static field values to static field values in afterPropertiesSet() method.

For example:

@Component
public class FileUploadUtils implements InitializingBean
{
    private static String endpoint;
    private static String accessKeyId;
    private static String accessKeySecret;
    private static String bucketName;
    private static OSSClient ossClient;

    @Value("${app.fileUpload.oss.endpoint}")
    private String getEndpoint;

    @Value("${app.fileUpload.oss.accessKeyId}")
    private String getAccessKeyId;

    @Value("${app.fileUpload.oss.accessKeySecret}")
    private String getAccessKeySecret;

    @Value("${app.fileUpload.oss.bucketName}")
    private String getBucketName;

    @Override
    public void afterPropertiesSet() throws Exception {
        endpoint = getEndpoint;
        accessKeyId = getAccessKeyId;
        accessKeySecret = getAccessKeySecret;
        bucketName = getBucketName;
        ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
}

Background

Intellij IDEA tips inspection error when injecting MyBatis mapper Java interface using @Autowired

@Autowired
private MyMapper mapper;

Error Info

Could not autowire. No beans of 'MyMapper' type found.

Solutions

It is not really an error, but error tips are annoying.

Solution 1: Add @Repository or @Component annotation in top of MyBatis Mapper interface classes.

@Repository
public interface MyMapper {}

Solution 2: Using @Resource annotation to inject MyBatis Mapper interface classes.

@Resouce
private MyMapper mapper;

References

[1] Idea inspects batis mapper bean wrong

Background

Compare date in where clauses of MyBatis mapper XML query.

<if test="beginTime != null and beginTime != ''">
createTime >= #{beginTime} and
</if>

Error Info

nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String

Solutions

remove beginTime != '' in the <if> element of MyBatis mapper XML file.

<if test="beginTime != null">
createTime >= #{beginTime} and
</if>

Reasons

When you pass Date objects as a parameter to MyBatis mapper XML query, you can’t compare the Date object with a String object in MyBatis <if> elements.

Java SE

@Deprecated // programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists.
@FunctionalInterface
@Override // Indicates that a method declaration is intended to override a method declaration in a supertype.
@SuppressWarnings // Indicates that the named compiler warnings should be suppressed in the annotated element (and in all program elements contained in the annotated element).
@SafeVarargs // A programmer assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter.

Spring Projects

Spring

Bean declaration

@Component
@Controller
@Service
@Repository

Make a bean belong to a particular profile

@Profile("dev")
@Profile({"dev","test"})
// Only can contains one !string. Can't be like {"!dev","!test"}
@Profile("!dev")

Bean injection

@Autowired
@Resource

Specify injected bean name

@Qualifier("specificBeanName")

Bean initMethod and destroyMethod

@PostConstruct
public void init() {}
@PreDestroy
public void destroy() {}

Configurations

@Configuration
@Bean
@ConditionalOnBean
@ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication
@ConditionalExpression
@Conditional

Configuration file properties

@PropertySource

@PropertySource("classpath:my.properties")
public class MyProperties {}

@ConfigurationProperties

@ConfigurationProperties(prefix = "config.path")
@Configuration
@EnableConfigurationProperties
@Data
public class MyProperties {}
@Value("${databaseName}")
private String databaseName;

Spring MVC

Request

@Controller
@RestController
@RequestMapping
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

Request Information

@PathVariable
@RequestParam
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date datetime
@RequestParam @DateTimeFormat(pattern = "HH:mm:ss") LocalTime time
@ModelAttribute
@RequestBody
@RequestHeader

Response

@ResponseBody
@ResponseHeader
@ResponseStatus

Convert Request Parameter Types

/**
* This method used in your Controller,
* or you can put the method in your BaseController.
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Convert field type from string to Date
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(YourEnum.class, new YourEnumConverter());
}

Data Validation

@Valid
@Validated(groupClass)

Data Validation Constraints Annotations

See JavaEE Validation Constraints Annotations

Exception Handling

@ExceptionHandler

Spring Data Access

@Transactional(rollbackFor=Exception.class)

By default all RuntimeExceptions rollback transaction whereas checked exceptions don’t. This is an EJB legacy. You can configure this by using rollbackFor() and noRollbackFor() annotation parameters: @Transactional(rollbackFor=Exception.class). This will rollback transaction after throwing any exception.

Programatically and manually roll back

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

Spring Security

@EnableWebSecurity

Spring Boot

Spring boot basic configuration

@SpringBootApplication
  • @SpringBootApplication = @Configuration + @ComponentScan + @EnableAutoConfiguration
  • @Configuration: This annotation marks a class as a Configuration class for Java-based configuration. This is particularly important if you favor Java-based configuration over XML configuration.
  • @ComponentScan: This annotation enables component-scanning so that the web controller classes and other components you create will be automatically discovered and registered as beans in Spring’s Application Context.
  • @EnableAutoConfiguration: This annotation enables the magical auto-configuration feature of Spring Boot, which can automatically configure a lot of stuff for you.

Scan MyBatis mappers

@MapperScan

For example

@MapperScan({"com.demo.dao", "com.demo.modules.**.dao"})

Wildcard

  • *: wildcard for one directory
  • **: wildcard for multiple level directory path

Java EE

Validation Constraints

validate object or string

@NotNull // a constrained CharSequence, Collection, Map, or Array is valid as long as it's not null, but it can be empty
@NotEmpty // a constrained CharSequence, Collection, Map, or Array is valid as long as it's not null and its size/length is greater than zero
@NotBlank // a constrained String is valid as long as it's not null and the trimmed length is greater than zero.
@Null
@Size // The annotated element size must be between the specified boundaries (included).
@Pattern // The annotated CharSequence must match the specified regular expression.
@Email

validate number

@Digits
@Min
@Max
@DecimalMax
@DecimalMin
@Positive
@PositiveOrZero
@Negative
@NegativeOrZero

validate datetime

@Future // The annotated element must be an instant, date or time in the future.
@FutureOrPresent
@Past // The annotated element must be an instant, date or time in the past.
@PastOrPresent

For more details refer to Java EE 8 javax.validation.constraints annotations

Jackson

JSON Serialization

Update format of serialized JSON value from Date type

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;

Update field name of serialized JSON

@JsonProperty(value = "user_password")
private String userPassword;

Ignore properties for JSON serialization

@JsonIgnore // for field
@JsonIgnoreProperties({"fieldname1", "fieldname2"}) // for POJO class
@JsonInclude // annotation used to define if certain "non-values" (nulls or empty values) should not be included when serializing

Serialize Enum to JSON String

@JsonSerialize(using = NameValueEnumSerializer.class)
public enum Type {
}

Property documentation, metadata

@JsonPropertyDescription

JSON Deserialization

Ignore Unknown Fields

@JsonIgnoreProperties(ignoreUnknown = true)

Convert JSON String to Date

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@DateTimeFormat(pattern = "HH:mm:ss")
private LocalTime alertTime;

Convert JSON String to Enum field (Note: The @JsonValue only deserialize for @RequestBody fields)

@JsonValue
public String getName() {
return name;
}

For more details refer to Jackson Annotations

Hibernate

@Entity
@Table
@Id
@GeneratedValue

MyBatis-Plus

Specify Table name

@TableName("t_user")

Specify primary key

@TableId(value = "id", type = IdType.AUTO)

Specify field is not as a column of table of database

@TableField(exist = false)

When field name same with keywords of database need use backquote to avoid SQL execution error

@TableField("`column`")
private String column;

Logic delete

@TableLogic(value = "0", delval = "1")
private Integer deleteFlag;

For more details refer to MyBatis-Plus Annotations

Lombok

POJO

@Data
@Getter/@Setter
@ToString
@ToString(callSuper = true)
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
@EqualsAndHashCode
@Builder // User.builder().name("Jack").build()
  • @Data: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor.

Generate a null-check statement

public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}

Result code

public NonNullExample(@NonNull Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person is marked @NonNull but is null");
}
this.name = person.getName();
}

Automatic resource management: Call your close() methods safely with no hassle.

public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}

To sneakily throw checked exceptions without actually declaring this in your method’s throws clause

@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}

Result code

public String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Lombok.sneakyThrow(e);
}
}

Annotate any class with a log annotation to let lombok generate a logger field.

@Log
@Log4j
@Log4j2
@Slf4j
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);

private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);

Others

@Value
@Synchronized
@With
@Getter(lazy=true)
@RequiredArgsConstructor(onConstructor_ = @Autowired)

For more details refer to Lombok features.

You can rolling Lombok Back with Delombok tool.

JavaScript Frameworks

jQuery

jsDelivr

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>

React.js

unpkg

<!-- dev -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- prod -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>

Vue.js

jsDelivr

<!-- dev -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- prod -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>

unpkg

<script src="https://unpkg.com/vue/dist/vue.js"></script>

UI Frameworks

jQuery-Based UI Frameworks

Bootstrap

jsDelivr

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>

LayUI

<link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui/css/layui.css" />
<script src="https://www.layuicdn.com/layui/layui.js"></script>

VueJS-based UI Frameworks

Element UI

<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

React-based UI Frameworks

Material UI

unpkg

<!-- dev -->
<script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js"></script>
<!-- prod -->
<script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.production.min.js"></script>

UI Components

Data Visualization

Apache Echarts

jsDelivr

<script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2/dist/echarts.min.js"></script>

Form Components

Rich Text Editors

wangEditor

<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/wangeditor@latest/dist/wangEditor.min.js"
></script>

Background

When I using MyBatis-Plus’ com.baomidou.mybatisplus.extension.plugins.pagination.Page object as one of parameters passing mapper XML to find my page data, there are some errors.

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

public interface CustomerMapper extends BaseMapper<Customer> {
List<Customer> findPage(@Param("page") Page page, @Param("entity") Customer customer);
}

Error Info

org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0,10' at line 58
### The error may exist in file [D:\jtg\Repositories\manage-console-app\target\classes\mapper\modules\sysmp\CrmCustomerMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select ... limit 0, 10 LIMIT ?,?
### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0,10' at line 58
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0,10' at line 58

Solutions

Using yourself defined Page object as the parameter, don’t use MyBatis-Plus Page object.

Reasons

When you using MyBatis-Plus Page object as parameter passing to mapper XML, The MyBatis-Plus will automate add the string LIMIT ?,? to end of the mapper XML SQL.

Background

I using Ant Design Table component to accomplish my list page. I return list data to frontend, but I got some error message in browser console.

Error Info

Warning: Each child in a list should have a unique "key" prop.
Solution

Solutions

Add a field “key” to each objects of the list

[{
key: 1,
createTime: "2021-01-07 11:13:00",
numberOfTopUp: 100,
totalNumber: 100
},
...
]

Reasons

Ant design defined this usage.

References

[1] Ant Design Components - Table

Principles

  • Member Variables of classes should use wrapper types for nullable. E.g. Integer, Long.

Initialize variables

  • Initialize Primitive type variables
byte byteVal = 1;
short shortVal = 1;
int intVal = 1;
long longVal = 1L;
float floatVal = 1.0F;
double doubleVal = 1.0;
boolean booleanVal = true;
char charVal = 'a';
  • Initialize Strings and array variables
String str = "hello";
int[] array = {1, 2, 3};
int[] array2 = new int[]{1, 2, 3};
int[] array3 = new int[3];
array3[0] = 1;
array3[1] = 2;
array3[2] = 3;
// objects
Object object = new Object();
  • Initialize List variables
List<Integer> list = new ArrayList(Arrays.asList(1, 2, 3));
  • Initialize Set variables
// Using Another Collection Instance
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));

// Using Anonymous Class
Set<Integer> set = new HashSet() {{
add(1);
add(2);
}};

// Using Stream Since Java 8
Set<String> set3 = Stream.of("a", "b", "c")
.collect(Collectors.toCollection(HashSet::new));
  • Initialize Maps variables
// Using Anonymous Class (Not recommend, Double Brace Initialization should not be used. Replace of to use map.put(key, value).)
Map<Integer, String> map = new HashMap<Integer, String>() {{
put(1, "one");
put(2, "two");
put(3, "three");
}};

// Using Stream Since Java 8
Map<String, Integer> map2 = Stream.of(new Object[][] {
{ "key1", 1 },
{ "key2", 2 },
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));

// Using a Stream of Map.Entry
Map<String, Integer> map3 = Stream.of(
new AbstractMap.SimpleEntry<>("key1", 1),
new AbstractMap.SimpleEntry<>("key2", 2))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Initialize constants

  • Initialize Primitive type constants
public static final byte byteVal = 1;
public static final short shortVal = 1;
public static final int intVal = 1;
public static final long longVal = 1L;
public static final float floatVal = 1.0F;
public static final double doubleVal = 1.0;
public static final boolean booleanVal = true;
public static final char charVal = 'a';
  • Initialize Strings and Array constants
public static final String str = "hello";
public static final int[] MY_ARRAY = {1, 2, 3};
  • Initialize List constants
public static final List<Integer> list = new ArrayList(Arrays.asList(1, 2, 3));
  • Initialize Set constants
public static final Set<Integer> SET = new HashSet();
static {
SET.add(1);
SET.add(2);
}
  • Initialize Map constants
public static final Map<Integer, String> MAP = new HashMap<Integer, String>();
static {
MAP.put(1, "one");
MAP.put(2, "two");
MAP.put(3, "three");
}

Initialize Immutable Container

  • Initialize Immutable List
// JDK 8 (Don't expose internal_list reference of unmodifiableList(List internale_list)). Arrays.asList() can't increase size, but it can modify its elements.
public static final List UNMODIFY_LIST = Collections.unmodifiableList(Arrays.asList(1, 2, 3));

// JDK 9 (Recommend, less space cost)
public static final List stringList = List.of("a", "b", "c");
  • Initialize Immutable Set
// JDK 8
public static final Set<String> stringSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));

// JDK 9 (Recommend)
public static final Set<String> stringSet2 = Set.of("a", "b", "c");
  • Initialize Immutable Map
// Immutable Map, JDK 8
public static final Map<Integer, String> UNMODIFY_MAP = Collections.unmodifiableMap(
new HashMap<Integer, String>()
{
{
put(1, "one");
put(2, "two");
put(3, "three");
};
});

// java 9, return ImmutableCollections (Recommend)
public static final Map<Integer, String> my_map2 = Map.of(1, "one", 2, "two");

// java 10, return ImmutableCollections (Recommend)
public static final Map<Integer, String> my_map3 = Map.ofEntries(
entry(1, "One"),
entry(2, "two"),
entry(3, "three"));

Enumeration Type vs Constants

  • If number of a set of constant is fixed, you should use enum type.
  • If number of a set of constant is increasing and variable, you should use constant variables.
public enum WeekDay {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
public static final int MONDAY = 0;
public static final int TUESDAY = 1;
public static final int WEDNESDAY = 2;
public static final int THURSDAY = 3;
public static final int FRIDAY = 4;
public static final int SATURDAY = 5;
public static final int SUNDAY = 6;

Type Formatting

Integer formatting

// Specifying length. 
String str2 = String.format("|%10d|", 101); // | 101|
// Left-justifying within the specified width.
String str3 = String.format("|%-10d|", 101); // |101 |
// Filling with zeroes.
String str4 = String.format("|%010d|", 101); // |0000000101|

Double formatting

Double value = 9.999;
String result = new DecimalFormat("#0.00").format(value);
double value = 3.1415926;
String result = String.format("value is: %.2f", value);
System.out.println(result); // value is: 3.14

Date formatting

Date date = new Date();
String result = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);

String formatting

String s = String.format("name is %s", name);
// Specify Maximum Number of Characters
String.format("|%.5s|", "Hello World"); // |Hello|
// Fill with zeros
String.format("%32s", Integer.toBinaryString(value)).replace(' ', '0')

If the template string contain %, you need replace with %%. For example,

String.format("%s increase 7%%", "Stock"); // Stock increase 7%
String.format("name like '%%%s%%'", "Jack"); // name like '%Jack%'

Value Comparison

Wrapper Object Comparison

Value type: 1. cache value(Integer: -128~127). 2. non-cache value. 3. null value.

Integer a = null; // 1, 128, null
Integer b = null; // 1, 128, null
boolean doesEqual = (a != null && a.equals(b)) || a == b;
System.out.println(doesEqual);

References

[1] Initialize a HashMap in Java

Sometimes we need to access our web projects running on local environments by domain names. We can reverse proxy a virtual domain by Nginx. Then we can use configured domain names to visit our local projects.

Downloading Nginx for Windows

Downloading Nginx for Windows from Nginx.

Configuring hosts file of Windows

Configuring virtual domains in C:\Windows\System32\drivers\etc\hosts

127.0.0.1 example1.com
127.0.0.1 example2.com

Check if the virtual domains are working

Open CMD terminal on Windows, and run the virtual domain test command. e.g. ping example1.com

Pinging example1.com [127.0.0.1] with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
...

Configuring Nginx Reverse Proxy

Configuring Nginx reverse proxy in conf\nginx.conf

http {
...
server {
listen 80;
server_name example1.com;
location / {
proxy_pass http://127.0.0.1:8081;
}
}

server {
listen 80;
server_name example2.com;
location / {
proxy_pass http://127.0.0.1:8082;
}
}

}

Starting Nginx

Starting Nginx

cd D:\nginx-1.18.0
start nginx.exe

Check if your Nginx server is up and running

Visit http://localhost to see the “welcome to nginx!” page

Visit

Visit the virtual domain (server name) URL http://example1.com/{your_app_request_path}

Warning: Ensure you are not using an HTTP proxy client such as v2rayN before accessing virtual domain URLs.

Stop Nginx

CMD of Windows

cd D:\nginx-1.18.0

# fast shutdown
nginx -s stop

# graceful shutdown
nginx -s quit

Git bash

cd D:\nginx-1.18.0

# fast shutdown
./nginx.exe -s stop

# graceful shutdown
./nginx.exe -s quit

Reload the configuration of Nginx

CMD of Windows

cd D:\nginx-1.18.0
nginx -s reload

Git bash

cd D:\nginx-1.18.0
./nginx.exe -s reload

Note

  1. Ensure that the ports 80, 433… where Nginx is listening are not occupied.
  2. Ensure you are not using an HTTP proxy client such as v2rayN before accessing virtual domain URLs.
  3. You must use Nginx commands to start and stop Nginx. Else you can’t stop the Nginx. Unless the Nginx process is killed in the task manager-Windows details or the Windows system is restarted.
  4. Before running start nginx, you must check if an Nginx server is running. If an Nginx server is running, you must run nginx -s stop first. Repeatedly running start nginx will start multiple Nginx servers, and you can’t stop all Nginx servers. Unless the Nginx process is killed in the task manager-Windows details or the Windows system is restarted.
0%