通用模板
2024年5月14日大约 9 分钟
运行/停止 Java 项目 - Linux
清理 Redis 缓存
#!/bin/bash
# 定义要清理的 Redis Key 数组
REDIS_KEY_PATTERNS=(
"xxx-token:*"
"xxx-code:*"
"xxx-key"
)
# Redis连接配置(根据需要修改)
REDIS_CLI="redis-cli"
# 如果需要认证,可以这样设置:
# REDIS_CLI="redis-cli -a your_password"
# 如果需要指定主机和端口:
# REDIS_CLI="redis-cli -h your_host -p your_port"
# 检查 Redis 是否可用
if ! $REDIS_CLI ping | grep -q "PONG"; then
echo "Redis 未启动或无法连接!"
exit 1
fi
echo "开始清理 Redis 缓存..."
# 初始化总计数
total_deleted=0
# 逐个模式清理
for pattern in "${REDIS_KEY_PATTERNS[@]}"; do
echo "清理模式: $pattern"
# 初始化变量
cursor=0
pattern_deleted=0
# 使用 SCAN 和 DEL 逐步清理键
while :; do
# SCAN 返回游标和匹配的键列表
result=$($REDIS_CLI scan $cursor match "$pattern" count 1000)
cursor=$(echo "$result" | head -n 1)
keys=$(echo "$result" | tail -n +2 | grep -v '^$')
# 删除匹配的键
if [[ ! -z "$keys" ]]; then
count=$(echo "$keys" | wc -l)
$REDIS_CLI del $keys > /dev/null 2>&1
pattern_deleted=$((pattern_deleted + count))
echo " 已删除 $count 个键"
fi
# 如果游标为 0,表示 SCAN 已完成
if [[ "$cursor" == "0" ]]; then
break
fi
done
total_deleted=$((total_deleted + pattern_deleted))
echo "模式 '$pattern' 完成: 删除 $pattern_deleted 个键"
echo
done
echo "Redis 缓存清理完成!"
echo "总共删除键数量: $total_deleted"运行
#!/bin/bash
# 运行参数
PORT=8080
JAVA_HOME=/usr/local/jdk21/jdk-21.0.2
JAR_FILE="./xxx.jar"
PROFILES=dev
# 检查JAR文件是否存在
if [ ! -f "$JAR_FILE" ]; then
echo "错误: JAR文件 $JAR_FILE 不存在!"
exit 1
fi
# 查找占用指定端口的Java进程ID
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "没有找到占用端口 $PORT 的Java进程。"
else
echo "停止 Java 端口号: $PORT , 进程 (PID: $PID) 中。。。"
# 使用kill命令优雅地停止Java进程
kill -15 $PID 2>/dev/null
# 添加超时机制,避免无限等待
COUNTER=0
while ps -p $PID > /dev/null 2>&1 && [ $COUNTER -lt 30 ]; do
echo "等待 Java 进程 (PID: $PID) 停止... ($((COUNTER+1))/30秒)"
sleep 1
COUNTER=$((COUNTER+1))
done
# 如果优雅停止失败,强制停止
if ps -p $PID > /dev/null 2>&1; then
echo "优雅停止失败,强制停止进程..."
kill -9 $PID 2>/dev/null
sleep 2
fi
echo "Java程序(端口: $PORT) 已完全停止。"
fi
echo "启动Java应用..."
# nohup 是后台启动,不会占用当前窗口
nohup $JAVA_HOME/bin/java \
-Dspring.profiles.active=$PROFILES \
-Xms2048m \
-Xmx2048m \
-Xmn1024m \
-jar "$JAR_FILE" > /dev/null 2>&1 &停止
# 程序运行端口号
PORT=8080
# 查找占用指定端口的Java进程ID
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "没有找到占用端口 $PORT 的Java进程。"
else
# 使用kill命令停止Java进程
kill -9 $PID
echo "停止 Java 端口号: $PORT , 进程 (PID: $PID) 中。。。"
# 等待Java程序完全停止(每秒检查一次,防止端口占用)
while ps -p $PID > /dev/null; do
echo "等待 Java 进程 (PID: $PID) 停止..."
sleep 1
done
echo "Java程序(占用端口号port: $PORT ) 已完全停止。"
fi停止-多端口
#!/bin/bash
# 定义要停止的端口数组
PORTS=(8080 7001 7002)
# 遍历端口数组并停止对应Java进程
for PORT in "${PORTS[@]}"; do
echo "处理端口: $PORT"
# 查找占用指定端口的Java进程ID
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "没有找到占用端口 $PORT 的Java进程。"
else
echo "停止 Java 端口号: $PORT , 进程 (PID: $PID)"
# 使用kill命令停止Java进程
kill -9 $PID
echo "Java程序(端口: $PORT) 已停止。"
fi
echo
done
echo "所有指定端口的Java程序停止完成。"运行/停止 Java 项目 - Win
Windowns 中关闭 Java 程序手动将 CMD 黑窗口关掉就行(管他多少个,直接右击【全部关闭】)。
运行
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 运行参数
set PORT=8080
set "JAVA_HOME=D:\start-package\back\jdk-8"
set "JAR_FILE=D:\start-package\back\apps\xxx.jar"
set CMD_TITLE=管理端
set PROFILES=dev
:: 设置控制台标题显示应用信息
title Java应用 - %CMD_TITLE% (端口:%PORT%)
:: 参数日志
echo JAVA_HOME: %JAVA_HOME%
echo JAR_FILE: %JAR_FILE%
echo PROFILES: %PROFILES%
:: 检查JAR文件是否存在
if not exist "%JAR_FILE%" (
echo 错误: JAR文件 %JAR_FILE% 不存在!
pause
exit /b 1
)
echo ✓ JAR文件存在
:: 检查Java是否可用
if not exist "%JAVA_HOME%\bin\java.exe" (
echo 错误: Java路径不正确或未安装!
echo 请检查JAVA_HOME: %JAVA_HOME%
pause
exit /b 1
)
echo ✓ Java环境正常
:: 查找占用指定端口的进程
echo 检查端口 %PORT% 占用情况...
set PID=
for /f "tokens=5" %%i in ('netstat -ano ^| findstr ":%PORT% " ^| findstr "LISTENING" 2^>nul') do (
set PID=%%i
)
if defined PID (
echo 发现占用端口 %PORT% 的进程 (PID: %PID%)
echo 正在停止该进程...
taskkill /pid %PID% /f >nul 2>&1
if errorlevel 1 (
echo 警告: 无法停止进程 %PID%,可能进程已退出
) else (
:: 等待进程停止
echo 等待进程停止...
timeout /t 3 /nobreak >nul
echo ✓ 进程已停止
)
) else (
echo ✓ 端口 %PORT% 未被占用
)
echo Java程序(端口: %PORT%) 已完全停止。
:START_APP
echo 启动Java应用...
:: 直接在当前窗口运行Java程序(会显示日志)
"%JAVA_HOME%\bin\java.exe" ^
-Dspring.profiles.active=%PROFILES% ^
-Xms2048m ^
-Xmx2048m ^
-Xmn1024m ^
-jar "%JAR_FILE%"停止
:: 此脚本用于关闭指定端口的 【Java进程】 和 【CMD窗口进程】
:: 进适合关闭单个端口,多个端口貌似兼容性不行,试了很多方法都不能关掉 CMD 窗口
@echo off
setlocal enabledelayedexpansion
:: 设置要停止的端口
set PORT=8080
:: 查找占用指定端口的进程
echo 检查端口 %PORT% 占用情况...
set PID=
for /f "tokens=5" %%i in ('netstat -ano ^| findstr ":%PORT% " ^| findstr "LISTENING" 2^>nul') do (
set PID=%%i
)
if defined PID (
echo 发现占用端口 %PORT% 的进程 (PID: %PID%)
echo 正在停止该进程...
:: 首先获取进程名称,用于查找相关的CMD窗口
set PROCESS_NAME=
for /f "tokens=1" %%n in ('wmic process where processid^="%PID%" get name 2^>nul ^| findstr /v "Name"') do (
set PROCESS_NAME=%%n
)
taskkill /pid %PID% /f >nul 2>&1
if errorlevel 1 (
echo 警告: 无法停止进程 %PID%,可能进程已退出
) else (
:: 等待进程停止
echo 等待进程停止...
timeout /t 2 /nobreak >nul
echo ✓ Java进程已停止
)
:: 查找并关闭运行Java程序的CMD窗口
echo 查找相关的CMD窗口...
set WINDOW_FOUND=0
for /f "tokens=2" %%w in ('tasklist /fi "imagename eq cmd.exe" /fo table /nh') do (
:: 检查这个CMD窗口是否在运行Java程序
for /f "tokens=1" %%j in ('wmic process where "name='cmd.exe' and processid='%%w'" get commandline 2^>nul ^| findstr /i "java.*jar"') do (
echo 关闭相关的CMD窗口 (PID: %%w)...
taskkill /pid %%w /f >nul 2>&1
set WINDOW_FOUND=1
)
)
if !WINDOW_FOUND!==1 (
echo ✓ CMD窗口已关闭
) else (
echo 未找到相关的CMD窗口,可能已自动关闭
)
) else (
echo ✓ 端口 %PORT% 未被占用
)
echo.
echo Java程序(端口: %PORT%) 已完全停止。
echo.
echo 所有指定端口的Java程序停止完成。
:: pause提示
有些极端场景,甲方服务器(Win 系统)无法联网,需要离线部署程序,跑过去帮甲方?呸!不可能!将前后端代码全部打包,让甲方自己传上去,无脑点击一下脚本文件就能自动运行最方便了。
在 Windows 中使用 bat 脚本快速启动一个 Java 程序的前后端,这里提供一个通用模板,下载下来,自己跟着说明玩一下,就能轻松实现一键在 Win 系统上运行 Java 程序。
数据库通用建表语句
Mysql
ALTER TABLE table_name
ADD COLUMN `version` int NULL DEFAULT NULL COMMENT '乐观锁',
ADD COLUMN `is_delete` int NULL DEFAULT NULL COMMENT '是否删除;0:否,1:是' AFTER `version`,
ADD COLUMN `create_by` varchar(255) NULL COMMENT '创建人' AFTER `create_time`,
ADD COLUMN `update_by` varchar(255) NULL COMMENT '修改人' AFTER `update_time`,
ADD COLUMN `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间' AFTER `is_delete`,
ADD COLUMN `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `create_time`;
-- MySQL 中,date 只包含年月日;datetime 的精度可选范围是 0~6,秒的小数位数,几乎都使用这个时间类型;
-- timestamp 与 datetime 类似,但内部会进行时区转换,用的较少Oracle
ALTER TABLE "table_name"
ADD (
"version" INT DEFAULT NULL,
"is_delete" INT DEFAULT NULL,
"create_by" VARCHAR2(255) DEFAULT NULL,
"update_by" VARCHAR2(255) DEFAULT NULL,
"create_time" DATE DEFAULT NULL,
"update_time" DATE DEFAULT NULL
-- Oracle 中,使用 DATE 存储时间是最常见的,它能存储的最小单位是秒;
-- 如有特殊业务对时间精度要求较高,可使用 TIMESTAMP 类型
-- "create_time" TIMESTAMP(0) DEFAULT NULL, -- 只存到秒,不包含小数秒部分
-- "create_time" TIMESTAMP, -- 默认小数秒精度为 6 位(微秒,最高精度)
-- "create_time" TIMESTAMP(3), -- 精确到毫秒
);
COMMENT ON COLUMN "table_name"."version" IS '乐观锁';
COMMENT ON COLUMN "table_name"."is_delete" IS '是否删除;0:否,1:是';
COMMENT ON COLUMN "table_name"."create_by" IS '创建人';
COMMENT ON COLUMN "table_name"."update_by" IS '修改人';
COMMENT ON COLUMN "table_name"."create_time" IS '创建时间';
COMMENT ON COLUMN "table_name"."update_time" IS '更新时间';DM
-- 达梦数据库通用建表语言
ALTER TABLE table_name ADD COLUMN "enable_flag" INT;
COMMENT ON COLUMN table_name."enable_flag" IS '0--已禁用 1--已启用';
ALTER TABLE table_name ADD COLUMN "is_delete" INT DEFAULT 0;
COMMENT ON COLUMN table_name."is_delete" IS '0--未删除 1--已删除';
ALTER TABLE table_name ADD COLUMN "create_by" VARCHAR(128);
COMMENT ON COLUMN table_name."create_by" IS '创建人';
ALTER TABLE table_name ADD COLUMN "update_by" VARCHAR(128);
COMMENT ON COLUMN table_name."update_by" IS '修改人';
ALTER TABLE table_name ADD COLUMN "create_time" DATE(0);
COMMENT ON COLUMN table_name."create_time" IS '创建时间';
ALTER TABLE table_name ADD COLUMN "update_time" DATE(0);
COMMENT ON COLUMN table_name."update_time" IS '更新时间';
-- 达梦数据库中,DATE 能精确到秒,最常用;DATETIME 精确到毫秒;
-- TIMESTAMP 最高支持微秒,即 TIMESTAMP(6)数据库通用 Mapper 语法
通用实体类
import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.util.Date; @Data public class BaseDomain { /** * 主键(使用自定义的 id 生成策略,详见 MP 官网) */ @TableId(value = "id", type = IdType.ASSIGN_ID) private String id; /** * 是否删除 0否 1是 */ @TableLogic private Integer deleteFlag; /** * 创建时间 */ @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; }分页查询
Service// Mybatis-Plus 分页查询示例 @Override public IPage<UserVo> getList(UserDto dto) { Page<User> page = new Page<>(dto.getPageNum, dto.getPageSize); return userMapper.selectUserByPage(page, dto); }Mapperpublic interface UserMapper extends BaseMapper<User> { IPage<UserVo> selectUserByPage(IPage<?> page, @Param("dto") UserDto dto); }mapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zjx.UserMapper"> <select id="selectUserByPage" resultType="com.zjx.vo.UserVo"> select u.id, u.name, addr.location, u.update_time from user u left join address addr on u.id = addr.user_id where u.is_delete = 0 <if test="dto.name != null and dto.name != ''"> and u.name like concat('%', #{dto.name}, '%') </if> <if test="dto.userTypes != null and dto.userTypes.size() > 0"> and u.type_id in <foreach collection="dto.userTypes" item="type" open="(" separator="," close=")"> #{type} </foreach> </if> <if test="dto.startTime != null and dto.endTime != null"> and u.update_time between #{dto.startTime} and #{dto.endTime} <!-- and u.update_time >= #{dto.startTime} and u.update_time <= #{dto.endTime} --> </if> -- 排序开始 ORDER BY <choose> <when test="dto.sortType == 0">u.age</when> <when test="dto.sortType == 1">u.age DESC</when> <otherwise>u.update_time DESC</otherwise> </choose> -- 排序结束 </select> </mapper>批量插入
Service// Mybatis-Plus 批量插入示例 @Override public void saveUsers(UserDto dto) { List<User> users = dto.getUsers().stream() .map(item -> item.setId(snowflakeGenerator.next().toString())) .collect(Collectors.toList()); return userMapper.batchInsert(users); }Mapperpublic interface UserMapper extends BaseMapper<User> { void batchInsert(@Param("users") List<User> users); }mapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zjx.UserMapper"> <insert id="batchInsert" parameterType="java.util.List"> insert into user(id, name, age) values <foreach collection="users" item="item" separator=","> ( #{item.id}, #{item.name}, #{item.age} ) </foreach> </select> </mapper>

