General#
Dependency management#
Pinning all three versions in the parent pom.xml#
Version reference
<dependencyManagement>
<dependencies>
<!-- 1. Spring Boot base version -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 2. Spring Cloud cloud-native base -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2025.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 3. Spring Cloud Alibaba full dependency core (key!) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2025.0.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Main class#
@MapperScan("asia.liminality.user.mapper")
@SpringBootApplication
@Slf4j
public class UserApplication {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext app = SpringApplication.run(UserApplication.class, args);
Environment env = app.getEnvironment();
String protocol = "http";
if (env.getProperty("server.ssl.key-store") != null) {
protocol = "https";
}
log.info("--/\n---------------------------------------------------------------------------------------\n\t" +
"Application '{}' is running! Access URLs:\n\t" +
"Local: \t\t{}://localhost:{}\n\t" +
"External: \t{}://{}:{}\n\t" +
"Profile(s): \t{}" +
"\n---------------------------------------------------------------------------------------",
env.getProperty("spring.application.name"),
protocol,
env.getProperty("server.port"),
protocol,
InetAddress.getLocalHost().getHostAddress(),
env.getProperty("server.port"),
env.getActiveProfiles());
}
}
domain#
DTO#
Result#
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private int code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
public static <T> Result<T> success() {
return new Result<>(200, "success", null);
}
public static <T> Result<T> failure(String message) {
return new Result<>(500, message, null);
}
public static <T> Result<T> failure(int code, String message) {
return new Result<>(code, message, null);
}
public static <T> Result<T> failure(String message, T data) {
return new Result<>(500, message, data);
}
}
Spring Cloud Gateway#
AuthGlobalFilter#
@Slf4j
@RequiredArgsConstructor
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
private final JwtUtil jwtUtil;
private static final List<String> WHITE_LIST = List.of(
"/auth/user/login",
"/auth/user/register"
);
// Check whether it's in the whitelist
private boolean isWhiteList(String path){
return WHITE_LIST.stream().anyMatch(path::startsWith);
}
private Mono<Void> reject(ServerWebExchange exchange){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().toString();
if (isWhiteList(path)) {
return chain.filter(exchange);
}
String token = request.getHeaders().getFirst("Authorization");
// Token is empty, deny access
if( token == null || token.isEmpty() ){
return reject( exchange );
}
// Verify the token
try {
Integer userId = jwtUtil.parseToken(token);
// TODO put userId into the request header
log.info("🚪 inject into request header");
} catch (Exception e) {
return reject(exchange);
}
return chain.filter( exchange );
}
// Filter priority; the smaller, the earlier
@Override
public int getOrder() {
return -1;
}
}