代码拉取完成,页面将自动刷新
#!/bin/bash
# 根据用户输入参数快速生成Java Web应用服务框架的命令行脚本程序
sh_folder="$(cd "$(dirname $0)"; pwd -P)"
# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
# For macOS, use two parameters
Darwin*) sedi=(-i "")
esac
# 命令行读取用户输入的参数并验证用户输入的值的有效性
# 如果输入无效则报错提示用户继续输入,直到用户输入的值为有效为止
# $1 保存参数默认值的变量名(用于间接引用)
# $2 验证参数有效性的正则表达式
# $3 参数无效时的错误提示信息
# $4 数字参数最大值<
# $5 数字参数最小值>
# 返回值保存在$1指定的变量中
function read_valid_arg()
{
# 输入的变量名
local varname=$1
#echo varname=$varname
# 输入的变量名的值
local defvalue=${!varname}
#[ -n "$4" ] && echo \$4=$4
#[ -n "$5" ] && echo \$5=$5
# macOS read 不支持 -i 参数
if [ "$(uname -s)" == Darwin ]
then
read -e -p "Enter使用默认值[$defvalue]:" input
local value="${input:-$defvalue}"
local isvalid=0
while true
do
[[ ! "$value" =~ $2 ]] && isvalid=1
# 判断数字是否在指定区间内区间
[ -n "$4" ] && [ $value -ge $4 ] && isvalid=1 && echo 超过最大值 $4
[ -n "$5" ] && [ $value -le $5 ] && isvalid=1 && echo 小于最小值 $5
if [ $isvalid -eq 0 ]
then
break;
else
isvalid=0
echo validate regex=$2
read -e -p "$3,Enter使用默认值[$defvalue]:" input
value="${input:-$1}"
fi
done
else
read -e -i "$defvalue" -p "Enter使用默认值:" input
local value="${input:-$defvalue}"
local isvalid=0
while true
do
[[ ! "$value" =~ $2 ]] && isvalid=1
# 判断数字是否在指定区间内区间
[ -n "$4" ] && [ $value -ge $4 ] && isvalid=1 && echo 超过最大值 $4
[ -n "$5" ] && [ $value -le $5 ] && isvalid=1 && echo 小于最小值 $5
if [ $isvalid -eq 0 ]
then
break;
else
isvalid=0
echo validate regex=$2
read -e -i "$defvalue" -p "$3:" input
value="${input:-$1}"
fi
done
fi
echo value=$value
# 将验证有效的值赋值给变量
eval "$varname=$value"
}
# 修改$1指定的文件名中名为$2的值为$3
# $1 key=value格式保存变量值的文件名
# $2 变量名key
# $3 变量的值value
# $4 sudo prefix
# 修改成功返回0, 失败退出脚本,$1 文件不存在则创建文件并添加key=value
function set_value(){
if [ ! -f "$1" ]
then
# 添加key=value对到文件
[ ! -d "$(dirname $1)" ] && mkdir -p "$(dirname $1)"
$4 echo -e "\n$2=$3" >> $1 || exit
return 0
fi
if $4 grep -q -E "^\s*$2\s*=.*$" $1
then
local r="$3"
r=${r//&/\\&}
r=${r//!/\\!}
r=${r//\//\\/}
# 如果存在key=value定义,则修改定义,否则向文件添加定义
$4 sed "${sedi[@]}" -r "s/(^\s*$2\s*=).*$/\\1$r/g" $1 || exit
return 0
fi
if $4 grep -q -E "^(#+\s*)+$2\s*=.*$" $1
then
local r="$3"
r=${r//&/\\&}
r=${r//!/\\!}
# 如果存在#开头的key=value(无效)定义,添加key=value对到找到行之后
$4 sed "${sedi[@]}" -r "/^(#+\s*)+$2\s*=.*$/a\\$2=$r" "$1" || exit
return 0
fi
# 添加key=value对到文件
$4 bash -c "echo ;echo $2=$3 >> $1" || exit
return 0
}
# 查找xml文件中指定tag的起始和结束标志
# 执行成功 tag_begin 保存起始标志行号,tag_end 保存结束标志行号
# $1 xml file
# $2 tag name, tag为.分割节点的字符串,如 database.jdbc
# 正常执行返回0,
# $1 不存在,$2为空返回255
# 有多个相同节点,没找到节点则失败返回255
function find_xml_tags()
{
find_xml_tag_begin=
find_xml_tag_end=
if [ -f "$1" ] && [ -n "$2" ]
then
# 将.分割的节点名转为数组
local array=(${2//./ })
local size=${#array[@]}
#echo size=$size
if [ $size -ge 1 ]
then
local tag=${array[0]}
[ -z "$tag" ] && return 255
# 查找第一个节点
tag_begin=$(sed -n -r "/<\s*$tag/=" "$1" ) && \
tag_end=$(sed -n -r "/<\/\s*$tag\s*>/=" "$1" )
local ab=($tag_begin)
local ae=($tag_end)
# 找到标记数量不是1则失败返回
if [ ${#ab[@]} -ne 1 ] || [ ${#ae[@]} -ne 1 ] ; then return 255 ; fi
#echo $tag tag_begin=$tag_begin tag_end=$tag_end
# 根据第一个顶级节点给定的行号范围循环查找所有其他子节点
# 以后的每次循环都在上次找到的行号范围内查找,会一步步缩小范围
for (( i = 1 ; i < $size ; i++ ))
do
tag=${array[i]}
[ -z "$tag" ] && return 255
# 在$tag_begin,tag_end给定范围的值内查找
local b=$(sed -n "$tag_begin,${tag_end}p" "$1" | sed -n -r "/<\s*$tag/=")
local e=$(sed -n "$tag_begin,${tag_end}p" "$1" | sed -n -r "/<\/\s*$tag\s*>/=")
local ab=($b)
local ae=($e)
# 找到标记数量不是1则失败返回
if [ ${#ab[@]} -ne 1 ] || [ ${#ae[@]} -ne 1 ] ; then return 255 ; fi
#echo b=$b e=$e
# b,e都是相对位置,在这里要转换为整文件的行号
let "tag_end=$tag_begin+$e-1"
let "tag_begin=$tag_begin+$b-1"
#echo $tag tag_begin=$tag_begin tag_end=$tag_end
done
return 0
fi
fi
return 255
}
# 设置xml文件中指定property的值,
# $1 xml file
# $2 .分割的节点的字符串,如 database.jdbc
# $3 value
# 正常执行返回0
# $1 不存在,$2为空返回255
# 有多个相同节点,没找到节点则失败返回255
# sed 修改文件失败返回sed错误代码
function set_xml_value()
{
find_xml_tags "$1" "$2" || exit
local last=${2##*.}
sed "${sedi[@]}" -r "$tag_begin,${tag_end}s!(<\s*$last.*>).*(</\s*$last\s*>)!\1$3\2!1" "$1" || exit
}
#set_xml_value $sh_folder/template/myrpc-local/src/main/resources/defaultConfig.xml server.start false
# find_xml_tags $sh_folder/template/myrpc-local/src/main/resources/defaultConfig.xml database.jdbc.schema && \
# echo tag_begin=$tag_begin tag_end=$tag_end && \
# sed -n "$tag_begin,${tag_end}p" $sh_folder/template/myrpc-local/src/main/resources/defaultConfig.xml
# sed -i -r "$tag_begin,${tag_end}s!(<\s*schema.*>).*(</\s*schema\s*>)!\1hello\2!1" $sh_folder/template/myrpc-local/src/main/resources/defaultConfig.xml
#exit
# 检查输入的字符串是否代表true含义
# $1
function istrue()
{
[[ "$1" =~ ^(true|y(es)?|on|1)$ ]]
}
# 检查输入的字符串是否代表true含义
# $1
function notrue()
{
[[ ! "$1" =~ ^(true|y(es)?|on|1)$ ]]
}
# 解析输入的URL返回域名部分
# 如果输入参数不是URL,返回空
# $1 URL
function host_of_url()
{
[[ "$1" =~ ^https?://([[:alnum:]\.]+) ]] && echo ${BASH_REMATCH[1]}
}
pushd "$sh_folder"
status_f="$sh_folder/rpcgen_status"
############################################################
# 创建初始的用户配置 #
# rpcgen_status 为保存用户配置的文件, #
# 如果不存在则从 rpcgen_status.init 复制一份 #
############################################################
[ -f "$sh_folder/rpcgen_status" ] || cp "$status_f.init" "$status_f" || exit
source "$status_f" || exit
############################################################
# 提示用户输入项目配置参数 #
############################################################
grep -B6 'start=' "$status_f" | head -n 6
#########################projectname########################
[ -z "$projectname" ] && projectname=hello-world
grep -B7 'projectname=' "$status_f" | head -n 7
read_valid_arg projectname "$projectname_rx" "无效的项目名称,请重新输入"
echo projectname=$projectname
###########################package##########################
[ -z "$package" ] && package=com.mycompany
grep -B7 'package=' "$status_f" | head -n 7
read_valid_arg package "$package_rx" "无效的包名,请重新输入"
echo package=$package
###########################prj_package##########################
[ -z "$prj_package" ] && prj_package=$package.${projectname//-/_}
grep -B4 'prj_package=' "$status_f" | head -n 4
read_valid_arg prj_package "$prj_package_rx" "无效的包名,请重新输入"
echo prj_package=$prj_package
###########################service##########################
[ -z "$service" ] && service=$(to_camel_case "${projectname}")
grep -B8 'service=' "$status_f" | head -n 8
read_valid_arg service "$service_rx" "无效的类名,请重新输入"
echo service=$service
###########################groupid##########################
[ -z "$groupid" ] && groupid=$package
grep -B8 'groupid=' "$status_f" | head -n 8
read_valid_arg groupid "$groupid_rx" "无效的groupId,请重新输入"
echo groupid=$groupid
###########################artifactid#######################
[ -z "$artifactid" ] && artifactid=$projectname
grep -B8 'artifactid=' "$status_f" | head -n 8
read_valid_arg artifactid "$artifactid_rx" "无效的artifactId,请重新输入"
echo artifactid=$artifactid
###########################version##########################
[ -z "$version" ] && version=0.0.0-SNAPSHOT
grep -B5 'version=' "$status_f" | head -n 5
read_valid_arg version "$version_rx" "无效的版本号,请重新输入"
echo version=$version
###########################prjurl##########################
# 将 . 分割的package字符串转换为域名
myhost=$(echo "$package" | perl -lne 'print join ".", reverse split/\./;')
location=$myhost/$projectname
[ -z "$prjurl" ] && prjurl="https://$location"
grep -B6 'prjurl=' "$status_f" | head -n 6
read_valid_arg prjurl "$prjurl_rx" "无效的URL,请重新输入"
echo prjurl=$prjurl
###########################scmurl##########################
[[ "$prjurl" =~ ^[a-zA-Z0-9_-]+://(.+)$ ]] && location=${BASH_REMATCH[1]}
[ -z "$scmurl" ] && scmurl="scm:git:https://$location.git"
grep -B6 'scmurl=' "$status_f" | head -n 6
read_valid_arg scmurl "$scmurl_rx" "无效的URL,请重新输入"
echo scmurl=$scmurl
###########################author##########################
[ -z "$author" ] && author=unknow_author
grep -B6 'author=' "$status_f" | head -n 6
read_valid_arg author "$author_rx" "无效的作者名,请重新输入"
echo author=$author
###########################email###########################
[ -z "$email" ] && email=$author@$myhost
grep -B4 'email=' "$status_f" | head -n 4
read_valid_arg email "$email_rx" "无效的email,请重新输入"
echo email=$email
###########################homepage###########################
[ -z "$homepage" ] && homepage=http://$myhost/$author
grep -B4 'homepage=' "$status_f" | head -n 4
read_valid_arg homepage "$homepage_rx" "无效的URL,请重新输入"
echo homepage=$homepage
#####################thrift_java_client#####################
[ -z "$thrift_java_client" ] && thrift_java_client=yes
grep -B4 'thrift_java_client=' "$status_f" | head -n 4
read_valid_arg thrift_java_client "$thrift_java_client_rx" "输入无效,请重新输入[y(es)|n(o)|true|false|on|off|0|1]"
echo thrift_java_client=$thrift_java_client
#####################thrift_cpp_client#####################
[ -z "$thrift_cpp_client" ] && thrift_cpp_client=no
grep -B4 'thrift_cpp_client=' "$status_f" | head -n 4
read_valid_arg thrift_cpp_client "$thrift_cpp_client_rx" "输入无效,请重新输入[y(es)|n(o)|true|false|on|off|0|1]"
echo thrift_cpp_client=$thrift_cpp_client
if istrue "$thrift_cpp_client"
then
###########################namespace_cpp##########################
[ -z "$namespace_cpp" ] && namespace_cpp=${package/*./}
grep -B8 'namespace_cpp=' "$status_f" | head -n 8
read_valid_arg namespace_cpp "$namespace_cpp_rx" "无效的namespace,请重新输入"
echo namespace_cpp=$namespace_cpp
fi
#######################service_restful_port#################
[ -z "$service_restful_port" ] && service_restful_port=8080
grep -B3 'service_restful_port=' "$status_f" | head -n 3
read_valid_arg service_restful_port "$service_restful_port_rx" "无效的端口号,请重新输入" 65535
echo service_restful_port=$service_restful_port
# 如果不需要thrft client,就不需要指定相关的端口
[ -z "$service_port" ] && service_port=28081
if istrue "$thrift_java_client" || istrue "$thrift_cpp_client"
then
###########################service_port#####################
grep -B3 'service_port=' "$status_f" | head -n 3
read_valid_arg service_port "$service_port_rx" "无效的端口号,请重新输入" 65535
echo service_port=$service_port
fi
########################service_xhr_port####################
[ -z "$service_xhr_port" ] && service_xhr_port=28082
grep -B3 'service_xhr_port=' "$status_f" | head -n 3
read_valid_arg service_xhr_port "$service_xhr_port_rx" "无效的端口号,请重新输入" 65535
echo service_xhr_port=$service_xhr_port
########################保存用户输入的参数##################
set_value "$status_f" projectname $projectname
set_value "$status_f" package $package
set_value "$status_f" prj_package $prj_package
set_value "$status_f" service $service
set_value "$status_f" groupid $groupid
set_value "$status_f" artifactid $artifactid
set_value "$status_f" version $version
set_value "$status_f" prjurl $prjurl
set_value "$status_f" scmurl $scmurl
set_value "$status_f" author $author
set_value "$status_f" email $email
set_value "$status_f" homepage $homepage
set_value "$status_f" thrift_java_client $thrift_java_client
set_value "$status_f" thrift_cpp_client $thrift_cpp_client
set_value "$status_f" namespace_cpp $namespace_cpp
set_value "$status_f" service_restful_port $service_restful_port
set_value "$status_f" service_port $service_port
set_value "$status_f" service_xhr_port $service_xhr_port
echo "############################################################"
echo "# 开始生成项目框架 #"
echo "############################################################"
echo "##########remove target ####################################"
rm -fr target && mkdir target 2>/dev/null
pushd target 1>/dev/null || exit
echo "##########copy ../template to target #######################"
cp -r ../template . || exit
./template/clean_mprj.sh ./template || exit
## 排除可能会由编译工具生成的 target,bin,build 文件夹和日志文件
echo "##########delete 'target','bin','build' folder in template #"
find template \( -name target -o -name bin -o -name build \) -type d -exec rm -fr "{}" \; || exit
echo "##########delete *.log folder in template ##################"
find template \( -name *.log -o -name .DS_Store \) -type f -delete || exit
echo "##########refactor file name ###############################"
## 文件路径改名,排除可能会由编译工具生成的 target,bin,build 文件夹和日志文件
find template -type f ! -path */target/* ! -path */bin/* ! -path */build/* | while read fname;
do
## 替换文件路径中所有myorg,myrpc,Myrpc字符串生成新的路径
_file=${fname/template/$projectname}
## 替换一级子文件夹名字
_file=${_file/myrpc/$projectname}
## 替换java包名
_file=${_file/myorg\/myrpc/${prj_package//.//}}
_file=${_file//myrpc/${projectname//-/_}}
_file=${_file//Myrpc/$service}
## echo rename $fname to $_file
parent=$(dirname $_file)
## 为移动的文件创建所有父级文件夹
[ -d "$parent" ] || mkdir -p $parent 1>/dev/null || exit
mv $fname $_file || exit
done || exit
echo "##########delete clean empty folder in template ############"
find template -type d -empty -delete
[ ! -d template ] || echo "WARNNING:template folder is not empty"
# 如果不需要thrft client,就不需要指定相关的项目
if ! istrue "$thrift_java_client"
then
echo "##########REMOVE java client prject folder##################"
rm -fr $projectname/$projectname-client || exit
rm -fr $projectname/$projectname-client-base || exit
rm -fr $projectname/$projectname-client-thrifty || exit
echo "##########REMOVE java client prject form pom.xml############"
sed "${sedi[@]}" "s|<module>myrpc-client</module>||g" "$projectname/pom.xml" || exit
sed "${sedi[@]}" "s|<module>myrpc-client-base</module>||g" "$projectname/pom.xml" || exit
sed "${sedi[@]}" "s|<module>myrpc-client-thrifty</module>||g" "$projectname/pom.xml" || exit
fi
# 如果不需要thrft c++ client,就不需要指定相关的项目
if ! istrue "$thrift_cpp_client"
then
echo "##########REMOVE c++ client prject folder##################"
rm -fr $projectname/$projectname-client-cpp || exit
echo "##########REMOVE c++ client prject form pom.xml############"
sed "${sedi[@]}" "s|<module>myrpc-client-cpp</module>||g" "$projectname/pom.xml" || exit
fi
if notrue "$thrift_java_client" && notrue "$thrift_cpp_client"
then
echo "##########Set server.start to false in defaultConfig.xml####"
set_xml_value $projectname/$projectname-local/src/main/resources/defaultConfig.xml server.start false || exit
fi
echo "##########refact all pom.xml file ##########################"
find $projectname -name pom.xml -type f | while read fname;
do
[ "$prjurl" = "https://myhost/myrpc" ] || sed "${sedi[@]}" "s!<url>https://myhost/myrpc!<url>$prjurl!g" "$fname" || exit
[ "$scmurl" = "scm:git:https://myhost/myrpc.git" ] || sed "${sedi[@]}" "s!scm:git:https://myhost/myrpc.git!$scmurl!g" "$fname" || exit
[ "$email" = "unknow_author@myhost" ] || sed "${sedi[@]}" "s!<email>unknow_author@myhost!<email>$email!g" "$fname" || exit
[ "$homepage" = "https://myhost/unknow_author" ] || sed "${sedi[@]}" "s!<url>https://myhost/unknow_author!<url>$homepage!g" "$fname" || exit
[ "$author" = "unknow_author" ] || sed "${sedi[@]}" "s/unknow_author/$author/g" "$fname" || exit
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" -r "s/<(artifactId|name|module)>myrpc/<\\1>$projectname/g" "$fname" || exit
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" -r "s/myrpc-/$projectname-/g" "$fname" || exit
[ "$groupid" = "mygroupid" ] || sed "${sedi[@]}" "s/mygroupid/$groupid/g" "$fname" || exit
[ "$version" = "0.0.0-SNAPSHOT" ] || sed "${sedi[@]}" "s/0.0.0-SNAPSHOT/$version/g" "$fname" || exit
done || exit
echo "##########refact all source file ###########################"
find $projectname ! -name *.jpg ! -name *.png ! -name *.jar -type f | while read fname;
do
echo refact $fname
[ "$prjurl" = "https://myhost/myrpc" ] || sed "${sedi[@]}" "s!https://myhost/myrpc!$prjurl!g" "$fname" || exit
[ "$email" = "unknow_author@myhost" ] || sed "${sedi[@]}" "s!unknow_author@myhost!$email!g" "$fname" || exit
sed "${sedi[@]}" "s/myhost/$myhost/g" "$fname" || exit
[ "$author" = "unknow_author" ] || sed "${sedi[@]}" "s/unknow_author/$author/g" "$fname" || exit
# /myorg/myrpc/ 都是包名对应的路径
[ "$prj_package" = "myorg.myrpc" ] || sed "${sedi[@]}" "s!/myorg/myrpc/!/${prj_package/.//}/!g" "$fname" || exit
# 替换包名
#echo "repalce myorg.myrpc with $prj_package"
[ "$prj_package" = "myorg.myrpc" ] || sed "${sedi[@]}" "s/myorg\.myrpc/$prj_package/g" "$fname" || exit
#echo "repalce myorg_myrpc with $prj_package" for C++ preprocessor code
[ "$prj_package" = "myorg.myrpc" ] || sed "${sedi[@]}" "s/myorg_myrpc/${prj_package//./_}/g" "$fname" || exit
# myrpc- 都是文件夹名
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" "s/myrpc-/$projectname-/g" "$fname" || exit
# ".myrpc" /.myrpc 都是文件夹名
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" -r "s!(/|\")\\.myrpc!\\1.$projectname!g" "$fname" || exit
#echo "repalce myrpc with $projectname"
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" "s/myrpc/${projectname//-/_}/g" "$fname" || exit
# /myorg/ 都是包名对应的路径
[ "$package" = "myorg" ] || sed "${sedi[@]}" "s!/myorg/!/${package/.//}/!g" "$fname" || exit
PRJNAME=${projectname//-/_}
## 转大写的项目名称
## macOS下${PRJNAME^^}这种转大写的语法不支持
PRJNAME=$(echo $PRJNAME | awk '{print toupper($0)}')
#echo "repalce MYRPC with $PRJNAME"
[ "$projectname" = "myrpc" ] || sed "${sedi[@]}" "s/MYRPC/$PRJNAME/g" "$fname" || exit
if [[ "${fname##*.}" =~ cpp|cxx|tcc|cc|c\+\+|h|hpp|hh ]] ;
then
# C++代码修改namespace
echo "repace myorg with $namespace_cpp for namespace"
[ "$package" = "myorg" ] || sed "${sedi[@]}" "s/myorg/$namespace_cpp/g" "$fname" || exit
else
#echo "repalce myorg with $package"
[ "$package" = "myorg" ] || sed "${sedi[@]}" "s/myorg/$package/g" "$fname" || exit
fi
#echo "repalce Myrpc with $service"
[ "$service" = "Myrpc" ] || sed "${sedi[@]}" "s/Myrpc/$service/g" "$fname" || exit
#echo "repalce 8080 with $service_restful_port"
[ $service_restful_port -eq 8080 ] || sed "${sedi[@]}" "s/8080/$service_restful_port/g" "$fname" || exit
#echo "repalce 28081 with $service_port"
[ $service_port -eq 28081 ] || sed "${sedi[@]}" "s/28081/$service_port/g" "$fname" || exit
#echo "repalce 28082 with $service_xhr_port"
[ $service_xhr_port -eq 28082 ] || sed "${sedi[@]}" "s/28082/$service_xhr_port/g" "$fname" || exit
done || exit
############################################################
# 如果安装有maven,则编译重构的项目验证重构正确性 #
############################################################
pushd $projectname 1>/dev/null || exit
which mvn 1>/dev/null && mvn clean compile || exit
echo "############################################################"
echo "# $projectname 的框架源码生成完毕 "
echo "# 保存在 target/$projectname "
echo "# 现在你可以在此基础上开始做自己的业务设计了 #"
echo "# 请继续阅读 README.md, 了解业务设计的相关说明 #"
echo "############################################################"
popd 1>/dev/null || exit
popd 1>/dev/null || exit
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。