Gradle非常强大,很多开源项目已经开始使用Gradle来构建,这里记录一下使用过的Gradle相关小技巧。
修改Gradle本地缓存库地址:设置环境变量GRADLE_USER_HOME=E:\.gradle
打war包时排除掉特定文件:
war { rootSpec.exclude('**/logback-test.xml') }
。
Gradle非常强大,很多开源项目已经开始使用Gradle来构建,这里记录一下使用过的Gradle相关小技巧。
修改Gradle本地缓存库地址:设置环境变量GRADLE_USER_HOME=E:\.gradle
打war包时排除掉特定文件:
war { rootSpec.exclude('**/logback-test.xml') }
。
Linux中的iptables非常强大,但是用起来稍显复杂。如果只做端口转发,使用rinetd是一个非常不错的选择。
官方网站为:http://www.boutell.com/rinetd/
安装很简单:
wget http://www.boutell.com/rinetd/http/rinetd.tar.gz tar fxz rinetd.tar.gz cd rinetd make make install
修改配置文件:vim /etc/rinetd.conf ,例如
0.0.0.0 1234 dest_ip dest_port
其中0.0.0.0为本机要监听的IP,0.0.0.0表示所有IP都可以访问该转发服务。
1234为监听端口,dest_ip为转发目标的IP,dest_port为转发目标的端口。
在部署Java Web工程时,往往会在同一台服务器上同时部署多个不同的服务,如果每个服务都拷贝一份Jetty,会显得比较麻烦和冗余,如果将多个工程都放到同一个Jetty中,那么最多只有一个工程能有root context,其余的工程都得加个子context去访问,显得不够友好。通过一些sh脚本,可以实现使用一份Jetty来启动多个不同的服务。
创建一个工程目录,例如oms,在这其中新建一个bin目录,把相关shell脚本放在这里面。新建一个env.sh,内容如下:
#!/usr/bin/env bash if [ -z "$APP_NAME" ] ; then export APP_NAME=oms cd .. export NODE_PATH=$(pwd) export app_conf=$NODE_PATH/conf cd - fi export JETTY_RUN=$NODE_PATH/bin export JETTY_PID=$NODE_PATH/.jetty.pid export JETTY_ARGS=jetty.port=8080 export JETTY_LOGS=$NODE_PATH/logs JAVA_MEM_OPTS=" -server -XX:+UseParNewGC -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:-CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:Sof tRefLRUPolicyMSPerMB=0 -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:-HeapDumpOnOutOfMemoryError " JAVA_OPTS_EXT=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8 " JAVA_DEBUG=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8088 " export JAVA_OPTIONS="$JAVA_MEM_OPTS $JAVA_OPTS_EXT " #export JAVA_OPTIONS="$JAVA_OPTIONS $JAVA_DEBUG "
其中,APP_NAME 为该服务war包的名称。jetty.port为jetty服务要启动的端口,其他的为一些常规的java参数设置
再在该目录下新建一个shell脚本jetty.sh,内容如下:
#!/usr/bin/env bash DIR=`dirname $0` source $DIR/env.sh if [ -z "$JETTY_HOME" ] ; then echo "Please set JETTY_HOME" exit fi if [ ! -e ../conf/webapps ] ; then mkdir -p ../conf/webapps fi if [ ! -e ../logs ] ; then mkdir -p ../logs fi if [ ! -e ../conf/webapps/$APP_NAME.xml ] ; then conf=../conf/webapps/$APP_NAME.xml echo '<?xml version="1.0" encoding="ISO-8859-1"?>' >> $conf echo '<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">' >> $conf echo '<Configure class="org.eclipse.jetty.webapp.WebAppContext">' >> $conf echo ' <Set name="contextPath">/</Set>' >> $conf echo ' <Set name="war">'"$NODE_PATH/war/$APP_NAME.war</Set>" >> $conf echo ' <Set name="tempDirectory">'"$NODE_PATH/war/${APP_NAME}_exploded</Set>" >> $conf echo ' <Set name="extractWAR">true</Set>' >> $conf echo ' <Set name="copyWebDir">false</Set>' >> $conf echo ' <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>' >> $conf echo '</Configure>' >> $conf fi rm -rf $JETTY_HOME/webapps ln -s $NODE_PATH/conf/webapps $JETTY_HOME/webapps $JETTY_HOME/bin/jetty.sh $1
设置好JETTY_HOME,然后执行jetty.sh start,便可以自动创建相关需要的xml,并启动jetty。这里假设war包放在工程目录的war目录下,并且名字为APP_NAME.war。
由于jetty自己的启动脚本中将JAVA_OPTIONS变成了数组,数组变量在shell脚本之间是不能传递的,而jetty restart调用了自身shell来进行重启操作,因此在我们自己写的env.sh中设置的JAVA_OPTIONS在jetty restart时就失效了,参数不能传递过去。为了解决该问题,需要修改jetty自己的启动脚本jetty.sh,vim $JETTY_HOME/bin/jetty.sh,在最上方加上这段代码:
if [ -f $NODE_PATH/bin/env.sh ];then source $NODE_PATH/bin/env.sh fi
在shell脚本里面重新加载env.sh
有两套客户端,共用了同一个接口服务,通过Http方式交互,现在需要将两套客户端对应的接口服务分离。由于请求的uri完全一致,调用的接口也完全一致,只有Http头里面有一个字段,用来区分是来自哪个客户端的请求。于是考虑根据这个Http头字段来进行请求分发,不同的客户端对应到不同的服务端。
写了个简单的配置示例(nginx.conf),证实该方案是可行的:
location / { if ($http_t = "163"){ proxy_pass http://163.com; } if ($http_t = "baidu"){ proxy_pass http://baidu.com; } root html; index index.html index.htm; }
其中$http_为nginx配置文件中获取Http头字段的默认前缀,例如Http头中有个字段为t,那么$http_t就为该字段对应的值。当该值为163的时候,直接跳转到163网站,当该值为baidu的时候,直接跳转到百度网站。
处理完该事情后,对Http JSON接口协议的制定也有了一些新的认识,对于全局性的字段,建议放到Http头中进行传递,因为不需要解析包体就可以对该请求做一些简单分析和处理。对于接口相关性的字段,可以放在JSON包体中进行传递。