Commit 9bc7fb15 authored by xiezhi's avatar xiezhi

Initial commit: Java 17 HTTP server template

parents
{
"version": "1.0.0",
"name": "Java 8 Hello World",
"tags": ["java", "hello-world", "http-server", "java8"],
"description": "基于Java 8的Hello World控制台程序示例",
"init_commands": ["make install"],
"start_commands": ["make run"],
"stop_commands": ["make stop"],
"mapping_ports": {
"APP_PORT_1": 8080,
"APP_PORT_2": 8081,
"APP_PORT_3": 8082,
"APP_PORT_4": 8083
},
"deploy": [
{
"image_name": "java8-hello-world",
"app_access_entry": true,
"ports": [
{
"name": "APP_PORT_1",
"main_port": true,
"inner_access_env_key": "API_URL",
"open_access": true,
"open_access_env_key": "API_DOMAIN"
},
{
"name": "APP_PORT_2",
"main_port": false,
"inner_access_env_key": null,
"open_access": false,
"open_access_env_key": null
}
],
"docker_file_dir": "./",
"deploy_resources": {
"cpu_limit": 0.5,
"memory_limit": 2,
"storage_limit": 1
}
}
]
}
# 依赖文件
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# 环境变量文件
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# 构建输出
dist/
build/
out/
# 日志文件
*.log
# 运行时数据
pids
*.pid
*.seed
*.pid.lock
# 覆盖率目录
coverage/
.nyc_output
# 依赖目录
jspm_packages/
# 可选的npm缓存目录
.npm
# 可选的eslint缓存
.eslintcache
# 可选的REPL历史
.node_repl_history
# 输出目录
*.tgz
# Yarn完整性文件
.yarn-integrity
# dotenv环境变量文件
.env
# 编辑器目录和文件
.idea/
*.swp
*.swo
*~
# 操作系统生成的文件
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# 临时文件
*.tmp
*.temp
# 备份文件
*.bak
*.backup
{
"recommendations": [
"vscjava.vscode-java-pack",
"redhat.java",
"vscjava.vscode-java-debug",
"vscjava.vscode-java-test",
"vscjava.vscode-maven",
"vscjava.vscode-java-dependency",
"formulahendry.code-runner",
"editorconfig.editorconfig"
]
}
\ No newline at end of file
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug Current File",
"request": "launch",
"mainClass": "${file}",
"projectName": "java8-template",
"console": "integratedTerminal",
"stopOnEntry": false,
"internalConsoleOptions": "neverOpen"
}
]
}
# 使用OpenJDK 17作为基础镜像
FROM hb.eazytec-cloud.com/eazytec/eazydevelop-java:ubuntu22.04-java17-latest
# 设置工作目录
WORKDIR /app
# 复制源代码
COPY src/ ./src/
# 复制Makefile和启动脚本
COPY Makefile ./
COPY docker-entrypoint.sh ./
# 设置启动脚本权限
RUN chmod +x docker-entrypoint.sh
# 编译Java程序
RUN make install
# 创建JAR文件
RUN make jar
# 设置环境变量
ENV APP_PORT_1=8080
# 暴露端口
EXPOSE $APP_PORT_1
# 运行程序(HTTP服务器模式)
ENTRYPOINT ["./docker-entrypoint.sh"]
# 变量定义
APP_NAME = java17-hello-world
JAVA_VERSION = 17
MAIN_CLASS = com.example.HelloWorld
SOURCE_DIR = src/main/java
BUILD_DIR = build
CLASSES_DIR = $(BUILD_DIR)/classes
JAR_FILE = $(BUILD_DIR)/hello-world.jar
APP_PORT = $(or $(APP_PORT_1),8080)
LOG_FILE = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/.logs/app.log
PID_FILE = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/.logs/app.pid
# Java编译器设置
JAVAC = javac
JAVA = java
JAR = jar
# 编译标志
JAVAC_FLAGS = -source $(JAVA_VERSION) -target $(JAVA_VERSION) -d $(CLASSES_DIR) -encoding UTF-8
# 默认目标
.PHONY: all
all: install
# 安装命令
.PHONY: install
install:
@echo "检查 Java 版本..."
@$(JAVA) -version
@echo "检查项目是否已编译..."
@if [ ! -d "$(CLASSES_DIR)" ]; then \
echo "正在编译Java源代码..."; \
mkdir -p $(CLASSES_DIR); \
$(JAVAC) $(JAVAC_FLAGS) -cp $(SOURCE_DIR) $(SOURCE_DIR)/com/example/*.java; \
echo "✅ Java源代码编译完成"; \
else \
echo "✅ Java源代码已编译"; \
fi
@echo "✅ 安装完成!Java项目已准备就绪"
# 运行命令(后台运行HTTP服务器)
.PHONY: run
run: install
@echo "正在启动 Java HTTP 服务器..."
@mkdir -p $(dir $(LOG_FILE))
@if [ -f "$(PID_FILE)" ]; then \
echo "服务器已在运行中,PID: $$(cat $(PID_FILE))"; \
exit 1; \
fi
@echo "启动服务器在端口 $(APP_PORT)..."
@APP_PORT_1=$(APP_PORT) nohup $(JAVA) -Dfile.encoding=UTF-8 -cp $(CLASSES_DIR) $(MAIN_CLASS) > $(LOG_FILE) 2>&1 & echo $$! > $(PID_FILE)
@echo "✅ Java HTTP 服务器已启动,PID: $$(cat $(PID_FILE))"
@echo "服务器运行在: http://localhost:$(APP_PORT)/"
@echo "查看日志: tail -f $(LOG_FILE)"
# 停止命令
.PHONY: stop
stop: kill
# 强制杀死所有相关Java进程
.PHONY: kill
kill:
@echo "正在查找并杀死所有相关的Java进程..."
@PIDS=$$(ps aux | grep -E "java.*$(MAIN_CLASS)|java.*$(APP_NAME)" | grep -v grep | awk '{print $$2}'); \
if [ -n "$$PIDS" ]; then \
echo "找到相关进程: $$PIDS"; \
for PID in $$PIDS; do \
echo "正在杀死进程 $$PID..."; \
kill -9 $$PID 2>/dev/null || true; \
done; \
sleep 1; \
echo "✅ 所有相关Java进程已被强制停止"; \
else \
echo "未找到相关的Java进程"; \
fi
@rm -f $(PID_FILE)
@echo "✅ 强制停止操作完成"
# 重启命令
.PHONY: restart
restart: stop run
# 查看状态
.PHONY: status
status:
@if [ -f "$(PID_FILE)" ]; then \
PID=$$(cat $(PID_FILE)); \
if ps -p $$PID > /dev/null 2>&1; then \
echo "✅ 服务器正在运行,PID: $$PID"; \
echo "端口: $(APP_PORT)"; \
echo "日志: $(LOG_FILE)"; \
else \
echo "❌ 服务器未运行(PID文件存在但进程不存在)"; \
rm -f $(PID_FILE); \
fi; \
else \
echo "❌ 服务器未运行"; \
fi
# 创建JAR文件
.PHONY: jar
jar: install
@echo "创建JAR文件..."
$(JAR) cfe $(JAR_FILE) $(MAIN_CLASS) -C $(CLASSES_DIR) .
@echo "JAR文件已创建: $(JAR_FILE)"
# 运行JAR文件
.PHONY: run-jar
run-jar: jar
@echo "运行JAR文件..."
$(JAVA) -jar $(JAR_FILE)
# 清理编译文件
.PHONY: clean
clean:
@echo "清理编译文件..."
rm -rf $(BUILD_DIR)
@echo "清理完成!"
# 显示帮助信息
.PHONY: help
help:
@echo "Java 17 HTTP 服务器项目"
@echo ""
@echo "可用命令:"
@echo " make install - 安装依赖并编译项目"
@echo " make run - 启动HTTP服务器(后台运行)"
@echo " make stop - 停止HTTP服务器(优雅停止)"
@echo " make kill - 强制杀死所有相关Java进程"
@echo " make restart - 重启HTTP服务器"
@echo " make status - 查看服务器状态"
@echo " make jar - 创建JAR文件"
@echo " make run-jar - 运行JAR文件"
@echo " make clean - 清理编译文件"
@echo " make help - 显示此帮助信息"
@echo ""
@echo "示例:"
@echo " make run # 启动服务器"
@echo " make status # 查看状态"
@echo " make stop # 优雅停止服务器"
@echo " make kill # 强制停止所有相关进程"
@echo " make restart # 重启服务器"
@echo ""
@echo "环境变量:"
@echo " APP_PORT_1 - 服务器端口(默认: 8080)"
# Java 17 HTTP 服务器项目
这是一个使用Java 17编写的简单HTTP服务器示例,展示了基本的Java网络编程和HTTP服务实现。
## 项目结构
```
java17-template/
├── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ └── HelloWorld.java # 主程序文件
├── Dockerfile # Docker容器化配置
├── docker-entrypoint.sh # Docker启动脚本
├── Makefile # 编译和运行脚本
└── README.md # 项目说明文档
```
## 功能特性
- ✅ 基于Java 17的HTTP服务器
- ✅ 使用内置的com.sun.net.httpserver.HttpServer
- ✅ 支持环境变量配置端口
- ✅ 返回"Hello, World!"响应
- ✅ Makefile自动化编译、运行和管理
- ✅ 支持后台运行和进程管理
- ✅ Docker容器化支持
## 环境要求
- Java 17 或更高版本
- Make工具(可选,用于自动化构建)
- Docker(可选,用于容器化运行)
## 快速开始
### 方法一:直接运行
```bash
# 编译程序
javac -d build/classes -source 17 -target 17 src/main/java/com/example/HelloWorld.java
# 运行HTTP服务器
APP_PORT_1=8080 java -cp build/classes com.example.HelloWorld
```
### 方法二:使用Makefile
```bash
# 安装依赖并编译
make install
# 启动HTTP服务器(后台运行)
make run
# 查看服务器状态
make status
# 停止服务器
make stop
# 强制停止所有相关进程
make kill
# 重启服务器
make restart
# 创建JAR文件
make jar
# 运行JAR文件
make run-jar
# 清理编译文件
make clean
# 查看帮助
make help
```
### 方法三:使用Docker
```bash
# 构建Docker镜像
docker build -t java17-hello-world .
# 运行容器
docker run -p 8080:8080 java17-hello-world
# 运行容器并指定端口
docker run -p 9090:8080 -e APP_PORT_1=8080 java17-hello-world
```
## 服务器使用示例
### 启动服务器
```bash
make run
# 输出:
# ✅ Java HTTP 服务器已启动,PID: 12345
# 服务器运行在: http://localhost:8080/
```
### 访问服务器
```bash
curl http://localhost:8080/
# 输出:Hello, World!
```
### 查看服务器状态
```bash
make status
# 输出:
# ✅ 服务器正在运行,PID: 12345
# 端口: 8080
# 日志: /path/to/.logs/app.log
```
### 停止服务器
```bash
make stop
# 输出:
# ✅ 进程 12345 已被强制停止
# ✅ 服务器停止操作完成
```
## 代码说明
### HelloWorld.java
HTTP服务器类包含以下功能:
- **main方法**: 程序入口点,启动HTTP服务器
- **端口配置**: 从环境变量APP_PORT_1读取端口,默认8080
- **HTTP处理器**: 实现MyHandler类处理HTTP请求
- **服务器启动**: 使用com.sun.net.httpserver.HttpServer创建HTTP服务
### Makefile
提供了以下命令:
- `install`: 检查Java版本并编译源代码
- `run`: 启动HTTP服务器(后台运行)
- `stop`: 停止HTTP服务器(直接调用kill)
- `kill`: 强制停止所有相关Java进程
- `restart`: 重启HTTP服务器
- `status`: 查看服务器运行状态
- `jar`: 创建可执行的JAR文件
- `run-jar`: 运行JAR文件
- `clean`: 清理编译生成的文件
- `help`: 显示帮助信息
### Dockerfile
- 基于OpenJDK 17镜像
- 自动编译和运行HTTP服务器
- 支持端口配置(APP_PORT_1环境变量)
- 暴露8080端口
## 环境变量
- `APP_PORT_1`: HTTP服务器端口号(默认: 8080)
## 扩展建议
1. **添加更多路由**: 可以添加不同的URL路径处理
2. **静态文件服务**: 添加静态文件(HTML、CSS、JS)服务功能
3. **API接口**: 添加RESTful API接口
4. **日志记录**: 使用Log4j或SLF4J进行日志记录
5. **配置文件**: 添加properties或YAML配置文件支持
6. **Maven/Gradle**: 使用构建工具管理依赖
7. **健康检查**: 添加健康检查端点
8. **HTTPS支持**: 添加SSL/TLS支持
## 许可证
此项目仅用于学习和演示目的。
#!/bin/bash
# Java 8 HTTP 服务器容器启动脚本
set -e
echo "=== Java 8 HTTP 服务器容器启动 ==="
echo "Java版本: $(java -version 2>&1 | head -n 1)"
echo "工作目录: $(pwd)"
echo "端口: ${APP_PORT_1:-8080}"
echo ""
# 检查Java是否可用
if ! command -v java &> /dev/null; then
echo "错误: Java未安装或不在PATH中"
exit 1
fi
# 检查编译后的类文件是否存在
if [ ! -d "build/classes" ]; then
echo "编译Java源代码..."
make install
fi
# 运行HTTP服务器
echo "启动HTTP服务器..."
echo "服务器将在端口 ${APP_PORT_1:-8080} 上运行"
echo "=========================================="
exec java -cp build/classes com.example.HelloWorld
package com.example;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class HelloWorld {
public static void main(String[] args) throws IOException {
// 从环境变量获取端口,默认为8080
String portStr = System.getenv("APP_PORT_1");
int port = 8080;
if (portStr != null && !portStr.isEmpty()) {
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException e) {
System.err.println("无效的端口号: " + portStr + ",使用默认端口8080");
}
}
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
System.out.println("Server running at http://0.0.0.0:" + port + "/");
server.createContext("/", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange exchange) throws IOException {
String response = "Hello, World!";
exchange.sendResponseHeaders(200, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment