diff --git a/zheng-demo/pom.xml b/zheng-demo/pom.xml index 400db771..7fd94894 100644 --- a/zheng-demo/pom.xml +++ b/zheng-demo/pom.xml @@ -19,6 +19,8 @@ + zheng-demo-rpc-api + zheng-demo-rpc-service zheng-demo-web diff --git a/zheng-demo/zheng-demo-rpc-api/pom.xml b/zheng-demo/zheng-demo-rpc-api/pom.xml new file mode 100644 index 00000000..b0d5d5ad --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-api/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + + com.zheng + zheng-demo + 1.0.0 + + + zheng-demo-rpc-api + jar + + zheng-demo-rpc-api + http://www.zhangshuzheng.cn + + + UTF-8 + + + + + com.zheng + zheng-common + 1.0.0 + + + + + zheng-upms-rpc-api + + + src/main/java + + **/*.xml + + true + + + src/main/resources + + + + diff --git a/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoService.java b/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoService.java new file mode 100644 index 00000000..305f061c --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoService.java @@ -0,0 +1,11 @@ +package com.zheng.demo.rpc.api; + +/** + * 测试接口 + * Created by shuzheng on 2017/4/1. + */ +public interface DemoService { + + String sayHello(String name); + +} diff --git a/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoServiceMock.java b/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoServiceMock.java new file mode 100644 index 00000000..3c7c4d9a --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-api/src/main/java/com/zheng/demo/rpc/api/DemoServiceMock.java @@ -0,0 +1,14 @@ +package com.zheng.demo.rpc.api; + +/** + * 降级实现DemoService接口 + * Created by shuzheng on 2017/4/1. + */ +public class DemoServiceMock implements DemoService { + + @Override + public String sayHello(String name) { + return null; + } + +} diff --git a/zheng-demo/zheng-demo-rpc-service/pom.xml b/zheng-demo/zheng-demo-rpc-service/pom.xml new file mode 100644 index 00000000..5db32e85 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/pom.xml @@ -0,0 +1,130 @@ + + + 4.0.0 + + com.zheng + zheng-demo + 1.0.0 + + + ${project.parent.groupId} + zheng-demo-rpc-service + ${project.parent.version} + + + UTF-8 + + + + + ${project.parent.groupId} + zheng-demo-rpc-api + 1.0.0 + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.4 + + true + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + **/*.properties + + + + + maven-assembly-plugin + + src/main/assembly/assembly.xml + + + + make-assembly + package + + single + + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + UTF-8 + + + + org.codehaus.plexus + plexus-compiler-javac + 1.8.1 + + + + + maven-resources-plugin + 2.6 + + UTF-8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.10 + + true + true + + + + + + + src/main/resources + + **/*.sh + + + + src/main/resources + + **/*.bat + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/*.xml + **/*.properties + + + + src/main/resources + true + + + + diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/assembly.xml b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/assembly.xml new file mode 100644 index 00000000..afd9f75d --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/assembly.xml @@ -0,0 +1,25 @@ + + assembly + + tar.gz + + true + + + src/main/assembly/bin + bin + 0755 + + + src/main/assembly/conf + conf + 0644 + + + + + lib + runtime + + + \ No newline at end of file diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/dump.sh b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/dump.sh new file mode 100644 index 00000000..a3c66b05 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/dump.sh @@ -0,0 +1,94 @@ +#!/bin/bash +cd `dirname $0` +BIN_DIR=`pwd` +cd .. +DEPLOY_DIR=`pwd` +CONF_DIR=$DEPLOY_DIR/conf + +SERVER_NAME=`sed '/dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` +LOGS_FILE=`sed '/dubbo.log4j.file/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` + +if [ -z "$SERVER_NAME" ]; then + SERVER_NAME=`hostname` +fi + +PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'` +if [ -z "$PIDS" ]; then + echo "ERROR: The $SERVER_NAME does not started!" + exit 1 +fi + +LOGS_DIR="" +if [ -n "$LOGS_FILE" ]; then + LOGS_DIR=`dirname $LOGS_FILE` +else + LOGS_DIR=$DEPLOY_DIR/logs +fi +if [ ! -d $LOGS_DIR ]; then + mkdir $LOGS_DIR +fi +DUMP_DIR=$LOGS_DIR/dump +if [ ! -d $DUMP_DIR ]; then + mkdir $DUMP_DIR +fi +DUMP_DATE=`date +%Y%m%d%H%M%S` +DATE_DIR=$DUMP_DIR/$DUMP_DATE +if [ ! -d $DATE_DIR ]; then + mkdir $DATE_DIR +fi + +echo -e "Dumping the $SERVER_NAME ...\c" +for PID in $PIDS ; do + jstack $PID > $DATE_DIR/jstack-$PID.dump 2>&1 + echo -e ".\c" + jinfo $PID > $DATE_DIR/jinfo-$PID.dump 2>&1 + echo -e ".\c" + jstat -gcutil $PID > $DATE_DIR/jstat-gcutil-$PID.dump 2>&1 + echo -e ".\c" + jstat -gccapacity $PID > $DATE_DIR/jstat-gccapacity-$PID.dump 2>&1 + echo -e ".\c" + jmap $PID > $DATE_DIR/jmap-$PID.dump 2>&1 + echo -e ".\c" + jmap -heap $PID > $DATE_DIR/jmap-heap-$PID.dump 2>&1 + echo -e ".\c" + jmap -histo $PID > $DATE_DIR/jmap-histo-$PID.dump 2>&1 + echo -e ".\c" + if [ -r /usr/sbin/lsof ]; then + /usr/sbin/lsof -p $PID > $DATE_DIR/lsof-$PID.dump + echo -e ".\c" + fi +done + +if [ -r /bin/netstat ]; then +/bin/netstat -an > $DATE_DIR/netstat.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/iostat ]; then +/usr/bin/iostat > $DATE_DIR/iostat.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/mpstat ]; then +/usr/bin/mpstat > $DATE_DIR/mpstat.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/vmstat ]; then +/usr/bin/vmstat > $DATE_DIR/vmstat.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/free ]; then +/usr/bin/free -t > $DATE_DIR/free.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/sar ]; then +/usr/bin/sar > $DATE_DIR/sar.dump 2>&1 +echo -e ".\c" +fi +if [ -r /usr/bin/uptime ]; then +/usr/bin/uptime > $DATE_DIR/uptime.dump 2>&1 +echo -e ".\c" +fi + +echo "OK!" +echo "DUMP: $DATE_DIR" + + diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/restart.sh b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/restart.sh new file mode 100644 index 00000000..647ec195 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/restart.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd `dirname $0` +./stop.sh +./start.sh diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/server.sh b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/server.sh new file mode 100644 index 00000000..90947a5d --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/server.sh @@ -0,0 +1,24 @@ +#!/bin/bash +cd `dirname $0` +if [ "$1" = "start" ]; then + ./start.sh +else + if [ "$1" = "stop" ]; then + ./stop.sh + else + if [ "$1" = "debug" ]; then + ./start.sh debug + else + if [ "$1" = "restart" ]; then + ./restart.sh + else + if [ "$1" = "dump" ]; then + ./dump.sh + else + echo "ERROR: Please input argument: start or stop or debug or restart or dump" + exit 1 + fi + fi + fi + fi +fi diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.bat b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.bat new file mode 100644 index 00000000..1075749b --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.bat @@ -0,0 +1,22 @@ +@echo off & setlocal enabledelayedexpansion + +set LIB_JARS="" +cd ..\lib +for %%i in (*) do set LIB_JARS=!LIB_JARS!;..\lib\%%i +cd ..\bin + +if ""%1"" == ""debug"" goto debug +if ""%1"" == ""jmx"" goto jmx + +java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -classpath ..\conf;%LIB_JARS% com.alibaba.dubbo.container.Main +goto end + +:debug +java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -classpath ..\conf;%LIB_JARS% com.alibaba.dubbo.container.Main +goto end + +:jmx +java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -classpath ..\conf;%LIB_JARS% com.alibaba.dubbo.container.Main + +:end +pause \ No newline at end of file diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.sh b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.sh new file mode 100644 index 00000000..132d60a0 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/start.sh @@ -0,0 +1,89 @@ +#!/bin/bash +cd `dirname $0` +BIN_DIR=`pwd` +cd .. +DEPLOY_DIR=`pwd` +CONF_DIR=$DEPLOY_DIR/conf + + +SERVER_NAME=`sed '/dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` +SERVER_PROTOCOL=`sed '/dubbo.protocol.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` +SERVER_PORT=`sed '/dubbo.protocol.port/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` +LOGS_FILE=`sed '/dubbo.log4j.file/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` + +if [ -z "$SERVER_NAME" ]; then + SERVER_NAME=`hostname` +fi + +PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'` +if [ -n "$PIDS" ]; then + echo "ERROR: The $SERVER_NAME already started!" + echo "PID: $PIDS" + exit 1 +fi + +if [ -n "$SERVER_PORT" ]; then + SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PORT | wc -l` + if [ $SERVER_PORT_COUNT -gt 0 ]; then + echo "ERROR: The $SERVER_NAME port $SERVER_PORT already used!" + exit 1 + fi +fi + +LOGS_DIR="" +if [ -n "$LOGS_FILE" ]; then + LOGS_DIR=`dirname $LOGS_FILE` +else + LOGS_DIR=$DEPLOY_DIR/logs +fi +if [ ! -d $LOGS_DIR ]; then + mkdir $LOGS_DIR +fi +STDOUT_FILE=$LOGS_DIR/stdout.log + +LIB_DIR=$DEPLOY_DIR/lib +LIB_JARS=`ls $LIB_DIR|grep .jar|awk '{print "'$LIB_DIR'/"$0}'|tr "\n" ":"` + +LOCK_ZOOKEEPER_FILE="$LOGS_DIR/`echo $PWD|awk -F/ '{print $NF}'`.properties" +JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Ddubbo.registry.file=$LOCK_ZOOKEEPER_FILE" +JAVA_DEBUG_OPTS="" +if [ "$1" = "debug" ]; then + JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n " +fi +JAVA_JMX_OPTS="" +if [ "$1" = "jmx" ]; then + JAVA_JMX_OPTS=" -Djava.rmi.server.hostname=172.21.32.38 -Dcom.sun.management.jmxremote.port=1088 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false " +fi +JAVA_MEM_OPTS="" +BITS=`java -version 2>&1 | grep -i 64-bit` +if [ -n "$BITS" ]; then + JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 " +else + JAVA_MEM_OPTS=" -server -Xms1g -Xmx1g -XX:PermSize=128m -XX:SurvivorRatio=2 -XX:+UseParallelGC " +fi + +echo -e "Starting the $SERVER_NAME ...\c" +nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main > $STDOUT_FILE 2>&1 & + +COUNT=0 +while [ $COUNT -lt 1 ]; do + echo -e ".\c" + sleep 1 + if [ -n "$SERVER_PORT" ]; then + if [ "$SERVER_PROTOCOL" == "dubbo" ]; then + COUNT=`echo status | nc -i 1 172.21.32.38 $SERVER_PORT | grep -c OK` + else + COUNT=`netstat -an | grep $SERVER_PORT | wc -l` + fi + else + COUNT=`ps -f | grep java | grep "$DEPLOY_DIR" | awk '{print $2}' | wc -l` + fi + if [ $COUNT -gt 0 ]; then + break + fi +done + +echo "OK!" +PIDS=`ps -f | grep java | grep "$DEPLOY_DIR" | awk '{print $2}'` +echo "PID: $PIDS" +echo "STDOUT: $STDOUT_FILE" diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/stop.sh b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/stop.sh new file mode 100644 index 00000000..91bbd184 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/bin/stop.sh @@ -0,0 +1,44 @@ +#!/bin/bash +cd `dirname $0` +BIN_DIR=`pwd` +cd .. +DEPLOY_DIR=`pwd` +CONF_DIR=$DEPLOY_DIR/conf + +SERVER_NAME=`sed '/dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` + +if [ -z "$SERVER_NAME" ]; then + SERVER_NAME=`hostname` +fi + +PIDS=`ps -ef | grep java | grep "$CONF_DIR" |awk '{print $2}'` +if [ -z "$PIDS" ]; then + echo "ERROR: The $SERVER_NAME does not started!" + exit 1 +fi + +if [ "$1" != "skip" ]; then + $BIN_DIR/dump.sh +fi + +echo -e "Stopping the $SERVER_NAME ...\c" +for PID in $PIDS ; do + kill $PID > /dev/null 2>&1 +done + +COUNT=0 +while [ $COUNT -lt 1 ]; do + echo -e ".\c" + sleep 1 + COUNT=1 + for PID in $PIDS ; do + PID_EXIST=`ps -f -p $PID | grep java` + if [ -n "$PID_EXIST" ]; then + COUNT=0 + break + fi + done +done + +echo "OK!" +echo "PID: $PIDS" diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/assembly/conf/dubbo.properties b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/conf/dubbo.properties new file mode 100644 index 00000000..bbb9e15b --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/assembly/conf/dubbo.properties @@ -0,0 +1,28 @@ +## +# Copyright 1999-2011 Alibaba Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## +dubbo.container=log4j,spring +dubbo.application.name=zheng-demo-rpc-service +dubbo.application.owner= +#dubbo.registry.address=multicast://224.5.6.7:1234 +dubbo.registry.address=zookeeper://127.0.0.1:2181 +#dubbo.registry.address=redis://127.0.0.1:6379 +#dubbo.registry.address=dubbo://127.0.0.1:9090 +dubbo.monitor.protocol=registry +dubbo.protocol.name=dubbo +dubbo.protocol.port=20880 +dubbo.service.loadbalance=roundrobin +dubbo.log4j.file=logs/zheng-demo-rpc-service.log +dubbo.log4j.level=WARN \ No newline at end of file diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/java/com/zheng/demo/rpc/service/impl/DemoServiceImpl.java b/zheng-demo/zheng-demo-rpc-service/src/main/java/com/zheng/demo/rpc/service/impl/DemoServiceImpl.java new file mode 100644 index 00000000..a4d7480e --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/java/com/zheng/demo/rpc/service/impl/DemoServiceImpl.java @@ -0,0 +1,16 @@ +package com.zheng.demo.rpc.service.impl; + +import com.zheng.demo.rpc.api.DemoService; + +/** + * 实现DemoService接口 + * Created by shuzheng on 2017/4/1. + */ +public class DemoServiceImpl implements DemoService { + + @Override + public String sayHello(String name) { + return "hello " + name; + } + +} \ No newline at end of file diff --git a/zheng-demo/zheng-demo-rpc-service/src/main/resources/META-INF/spring/applicationContext-dubbo-service.xml b/zheng-demo/zheng-demo-rpc-service/src/main/resources/META-INF/spring/applicationContext-dubbo-service.xml new file mode 100644 index 00000000..e18fdda5 --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/main/resources/META-INF/spring/applicationContext-dubbo-service.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/zheng-demo/zheng-demo-rpc-service/src/test/java/com/zheng/AppTest.java b/zheng-demo/zheng-demo-rpc-service/src/test/java/com/zheng/AppTest.java new file mode 100644 index 00000000..62c3c90e --- /dev/null +++ b/zheng-demo/zheng-demo-rpc-service/src/test/java/com/zheng/AppTest.java @@ -0,0 +1,38 @@ +package com.zheng; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/zheng-demo/zheng-demo-web/pom.xml b/zheng-demo/zheng-demo-web/pom.xml index c7e593d4..f5b8c15d 100644 --- a/zheng-demo/zheng-demo-web/pom.xml +++ b/zheng-demo/zheng-demo-web/pom.xml @@ -21,6 +21,12 @@ 1.0.0 jar + + com.zheng + zheng-demo-rpc-api + 1.0.0 + jar + junit junit diff --git a/zheng-demo/zheng-demo-web/src/main/java/com/zheng/demo/web/controller/IndexController.java b/zheng-demo/zheng-demo-web/src/main/java/com/zheng/demo/web/controller/IndexController.java index 3d5e86d6..cf8dffe7 100644 --- a/zheng-demo/zheng-demo-web/src/main/java/com/zheng/demo/web/controller/IndexController.java +++ b/zheng-demo/zheng-demo-web/src/main/java/com/zheng/demo/web/controller/IndexController.java @@ -1,9 +1,11 @@ package com.zheng.demo.web.controller; import com.zheng.common.base.BaseController; +import com.zheng.demo.rpc.api.DemoService; import com.zheng.demo.web.model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @@ -21,6 +23,9 @@ public class IndexController extends BaseController { private static Logger _log = LoggerFactory.getLogger(IndexController.class); + @Autowired + private DemoService demoService; + /** * jsp视图 * @return @@ -37,7 +42,7 @@ public class IndexController extends BaseController { */ @RequestMapping(value = "/thymeleaf", method = RequestMethod.GET) public String thymeleaf(Model model) { - model.addAttribute("host", "http://www.zhangshuzheng.cn"); + model.addAttribute("host", demoService.sayHello("http://www.zhangshuzheng.cn/")); List users = new ArrayList<>(); User user = new User(); user.setId(1l); diff --git a/zheng-demo/zheng-demo-web/src/main/resources/applicationContext-dubbo-consumer.xml b/zheng-demo/zheng-demo-web/src/main/resources/applicationContext-dubbo-consumer.xml new file mode 100644 index 00000000..49e05758 --- /dev/null +++ b/zheng-demo/zheng-demo-web/src/main/resources/applicationContext-dubbo-consumer.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file