转载

码云推荐 | 基于 Netty 和 Spring 的服务端容器StartX

StartX (已更新至v1.3.1)

版本更新

- v1.0.0 支持http(s)
- v1.1.0 支持ws(s)
- v1.1.1 支持http(s)+ws(s)
- v1.2.1 支持文本socket
- v1.3.1 支持Maven打包部署

项目简介

Netty和Spring开发的服务端容器,支持Socket,WebSocket(SSL),HTTP(S),提供集成环境,能很快速的进入业务开发,对业务开发者透明,支持对各种通讯协议进行定制

源码结构

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─startx
│  │  │          └─core
│  │  │              ├─config                          #系统配置
│  │  │              │  ├─holder
│  │  │              │  └─reader
│  │  │              │      └─impl
│  │  │              ├─netty                           #网络通讯
│  │  │              │  ├─handler
│  │  │              │  ├─output
│  │  │              │  │  ├─http
│  │  │              │  │  ├─socket
│  │  │              │  │  └─wss
│  │  │              │  ├─pipeline
│  │  │              │  └─server
│  │  │              │      └─impl
│  │  │              ├─point                            #MVC框架
│  │  │              │  ├─anotation
│  │  │              │  └─factory
│  │  │              ├─system                           #系统变量
│  │  │              │  ├─constants
│  │  │              │  ├─model
│  │  │              │  └─param
│  │  │              └─tools                            #系统工具
│  │  ├─resources                                       #资源文件
│  │  └─test                                            #测试代码
│  │      └─com
│  │          └─startx
│  │              ├─action
│  │              └─test

启动方式

  • 导入maven项目
  • 打开Bootrap类
  • 新建一个测试类
  • 创建main函数
  • 调用Bootstrap.start()

修改配置(config.properties)

#项目启动端口
port=8081
#spring配置路径
springPath=classpath*:application.xml
#项目访问前缀(已实现)
endPoint=/j4
#是否开启ssl
isSSL=false
#若开启ssl,需要配置如下两个参数
jksPwd=your.pwd
jksPath=/your.jks
#配置使用websocketServer,同时支持ws(s)和http(s)
serverClass=com.startx.core.netty.server.impl.WebSocketServer

更多配置

/**
 * 监听端口
 */
private int port = 8080;
/**
 * boss线程数
 */
private int boss = 2;
/**
 * workder线程数
 */
private int worker = 4;
/**
 * spring配置路径
 */
private String springPath = "classpath*:application.xml";
/**
 * 项目访问前缀
 */
private String endPoint = "/";
/**
 * 是否为ssl
 */
private boolean isSSL = false;
/**
 * 静态资源目录
 */
private String resource = "/resource";
/**
 * endpoint扫描路径
 */
private String packages = "com.startx";
/**
 * 设置NettyServer启动类
 */
private String serverClass = "com.startx.core.netty.server.impl.HttpServer";
// 以下配置在ssl连接时使用
/**
 * jsk密码
 */
private String jksPwd;
/**
 * jsk路径
 */
private String jksPath;

代码测试

打开演示代码J4.java,右键即可运行

package com.startx.test;

import com.startx.core.Bootstrap;

public class J4 {
	
	public static void main(String[] args) throws Exception {
		
		Bootstrap.start();
		
	}
	
}

日志打印

2018-05-09 13:06:05 INFO  com.startx.core.netty.server.impl.HttpServer  - StartxConfig [port=8081, boss=2, worker=4, springPath=classpath*:application.xml, endPoint=/, isSSL=false, resource=/resource, jksPwd=your.pwd, jksPath=/your.jks, packages=com.startx, serverClass=com.startx.core.netty.server.impl.HttpServer]
2018-05-09 13:06:05 INFO  org.springframework.context.support.ClassPathXmlApplicationContext  - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4bec1f0c: startup date [Wed May 09 13:06:05 CST 2018]; root of context hierarchy
2018-05-09 13:06:05 INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader  - Loading XML bean definitions from URL [file:/E:/zhangminghu/startx/target/classes/application.xml]
2018-05-09 13:06:05 INFO  com.startx.core.accesspoint.factory.AccessPointFactory  - GET_/abc/def2_JSON
2018-05-09 13:06:05 INFO  com.startx.core.accesspoint.factory.AccessPointFactory  - GET_/abc/def3_JSON
2018-05-09 13:06:05 INFO  com.startx.core.accesspoint.factory.AccessPointFactory  - GET_/abc/def4_JSON
2018-05-09 13:06:05 INFO  com.startx.core.accesspoint.factory.AccessPointFactory  - GET_/abc/def1_JSON
2018-05-09 13:06:06 INFO  com.startx.core.netty.server.impl.HttpServer  - 
**************************    *********                     ******  ********************************
**************************  ***********                     ******  ********************************
**************************  ********* **************************************************************
**************************  ***   **************************************** *************************
**************************  ***     ********             *********     *** *************************
**************************   ***                                      **** *************************
**************************   ***                                      ***  *************************
**************************  ***                                       ***  *************************
**************************  ***                                        *** *************************
************************** ****                                        *** *************************
************************** ***                                         *** *************************
************************** ***     *****                    ****       *** *************************
************************** ***    ********               *********      ****************************
*****************************      *******  *****  ***** *********      ****************************
*****************************        **** ***********************       ****************************
*****************************            *******************            ****************************
****************************             *******************             ***************************
****************************             *******************             ***************************
****************************             *******************             ***************************
****************************              *****************              ***************************
****************************                ************                 ***************************
**************************  ***                                        *** *************************
**************************   ***                V1.3.1                ***  *************************
**************************   ****                                     **   *************************
****************************  ***   ******************************   ***   *************************
**********************************  ************************************   *************************
**************************************  *******************************    *************************
******************************* ******                        *******      *************************
2018-05-09 13:06:06 INFO  com.startx.core.netty.server.impl.HttpServer  - 服务已启动,端口号: 8081.

业务代码

package com.startx.action;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;

import com.startx.core.accesspoint.anotation.AccessPoint;
import com.startx.core.accesspoint.anotation.RequestMethod;
import com.startx.core.accesspoint.anotation.RequestPoint;
import com.startx.core.accesspoint.anotation.ResponseType;
import com.startx.core.netty.output.http.JsonOutput;
import com.startx.core.system.Colorfulogo;
import com.startx.core.system.param.HttpArgs;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpResponseStatus;

@Controller
@AccessPoint("/login")
public class LoginAction {
	
	@RequestPoint(value={"/empty/param"},method=RequestMethod.GET,type=ResponseType.JSON)
	public void emptyParam() {
		
		System.out.println("login...");
		
	}
	
	@RequestPoint(value={"/body/ctx/args"},method=RequestMethod.GET,type=ResponseType.JSON)
	public void test02(byte[] body,ChannelHandlerContext ctx,HttpArgs args) throws UnsupportedEncodingException {
		
		Map<String,Object> response = new HashMap<>();
		response.put("colorfulogo", Colorfulogo.get());
		JsonOutput.object(ctx, HttpResponseStatus.OK,response);
		
	}
	
	@RequestPoint(value={"/args/body"},method=RequestMethod.GET,type=ResponseType.JSON)
	public void test03(HttpArgs args,byte[] body) {
		
		System.out.println("login...");
		
	}
	
	@RequestPoint(value={"/args"},method=RequestMethod.GET,type=ResponseType.JSON)
	public Map<String,Object> test04(HttpArgs args) {
		
		System.out.println("login... ");
		Map<String,Object> response = new HashMap<>();
		response.put("colorfulogo", Colorfulogo.get());
		
		return response;
	}
	
}

打包部署

打包方法

- 下载V1.3.1源代码
- 导入Maven项目
- 执行maven打包命令(clean install)

打包配置

- pom.xml 配置assembly打包插件以及项目打jar包需要排除的配置文件
- assembly.xml 配置assembly打包脚本,这里主要关注需要打包到jar之外的配置文件得include

关键代码

  • pom.xml
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<version>2.4</version>
	<configuration>
		<!-- 注意添加排除目录到打包插件 -->
		<excludes>
			<exclude>**/logs/</exclude>
			<exclude>**/*.xml</exclude>
			<exclude>**/*.properties</exclude>
			<exclude>**/*.sh</exclude>
			<exclude>config</exclude>
		</excludes>
	</configuration>
</plugin>

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-assembly-plugin</artifactId>
	<version>2.4</version>
	<configuration>
		<descriptors>
			<descriptor>src/main/assembly/assembly.xml</descriptor>
		</descriptors>
	</configuration>
	<executions>
		<execution>
			<id>make-assembly</id>
			<phase>package</phase>
			<goals>
				<goal>single</goal>
			</goals>
		</execution>
	</executions>
</plugin>
  • assembly.xml
<assembly>
	<id>release</id>
	<formats>
		<format>tar.gz</format>
	</formats>
	<dependencySets>
		<!-- refer to http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_dependencySet -->
		<dependencySet>
			<useProjectArtifact>true</useProjectArtifact>
			<outputDirectory>lib</outputDirectory>
		</dependencySet>
	</dependencySets>
	<fileSets>
		<fileSet>
			<directory>logs</directory>
			<outputDirectory>logs</outputDirectory>
		</fileSet>
		<fileSet>
			<directory>target/classes</directory>
			<outputDirectory>conf</outputDirectory>
			<includes>
				<!-- 添加配置文件注意配置此处加入conf目录 -->
				<include>*.xml</include>
				<include>*.properties</include>
				<include>*.jks</include>
				<include>config/*</include>
			</includes>
		</fileSet>
		<fileSet>
			<directory>src/main/scripts</directory>
			<outputDirectory>bin</outputDirectory>
			<fileMode>0733</fileMode>
			<includes>
				<include>*.sh</include>
			</includes>
		</fileSet>
		<fileSet>
			<directory>libs</directory>
			<outputDirectory>lib</outputDirectory>
			<includes>
				<include>*.jar</include>
			</includes>
		</fileSet>
	</fileSets>

</assembly>

启动脚本

脚本文件startup.sh,实现了start,stop等命令,执行方式为:bin/startup.sh start|stop,这里关注两个配置项:

  • 启动类(启动之后的进程名,也就是启动示例的J4,可以自己配置)
  • JVM 参数,根据自己的服务器配置或优化经验进行调整

具体脚本请参见startup.sh

_ServerClass=com.startx.test.J4
JAVA_OPTS=" -server -Xms5120m -Xmx5120m -Xmn4096m -XX:MetaspaceSize=128M -verbose:gc -Xloggc:logs/gc.log -XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:MaxTenuringThreshold=10 -XX:SurvivorRatio=8 -XX:PermSize=128m -XX:MaxPermSize=128m 
-XX:+UseParNewGC  -Xss1024k"

执行编译

mvn clean install,得到xxx.tar.gz压缩包

解压之后结构如下:

├─bin                  #启动脚本
├─conf                 #项目配置文件
│  └─config            #项目子配置文件
└─lib                  #项目依赖包

部署服务

  • 上传代码到安装有jdk环境的Linux服务器
  • 执行代码转换脚本为unix格式: dos2unix bin/startup.sh
  • 启动程序或停止程序:bin/startup.sh start|stop
  • 会自动生成logs文件夹,日志内容为控制台输出日志
  • 当前自动生成的pid文件请勿删除,以防重复启动
  • 使用jps查看进程,能看到J4进程正在运行

注意事项

请修改为当前合适的配置,代码已移除具体配置,例如mysql地址

原文  https://gitee.com/sharegpj/StartX
正文到此结束
Loading...