作者 zhonglai

修改bug

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhonglai</groupId>
<artifactId>SocketHtml</artifactId>
<version>1.0.2</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 系统依赖 -->
<dependency>
<groupId>com.zhonglai</groupId>
<artifactId>core</artifactId>
<version>1.5.11</version>
</dependency>
<!-- nio -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Release Repository</name>
<url>http://code.part-timead.com:4781/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<name>Nexus Snapshot Repository</name>
<url>http://code.part-timead.com:4781/nexus/content/repositories/releases/</url>
</snapshotRepository>
</distributionManagement>
</project>
\ No newline at end of file
... ...
package com.zhonglai.socket.html;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
/**
* 基于JAVA AIO的,面向TCP/IP的,非阻塞式Sockect服务器框架类
*
* @author zer0
* @version 1.0
* @date 2015-2-15
*/
public class TcpServer {
private volatile Integer port;//服务器端口
private Channel channel;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
private ChannelInitializer channelInitializer;
public TcpServer(Integer port, ChannelInitializer channelInitializer){
this.port = port;
this.channelInitializer = channelInitializer;
}
/**
* 启动服务器
*
* @author zer0
* @version 1.0
* @date 2015-2-19
*/
public ChannelFuture startServer(){
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(channelInitializer)
.handler(new LoggingHandler(LogLevel.INFO))
.option(ChannelOption.SO_BACKLOG, 128); // 设置tcp协议的请求等待队列
try {
ChannelFuture future = bootstrap.bind(new InetSocketAddress(port)).sync();
channel = future.channel();
System.out.println("服务器已启动,端口:" + port);
return future;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public void destory(){
if (channel != null) {
channel.close();
}
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
... ...
package com.zhonglai.socket.html.action;
import com.google.gson.JsonObject;
public interface Base {
public void setParameter(JsonObject parameter);
}
... ...
package com.zhonglai.socket.html.action;
import com.google.gson.JsonObject;
/**
* 父类
*/
public class BaseAction implements Base{
protected JsonObject parameter;
public void setParameter(JsonObject parameter)
{
this.parameter = parameter;
}
}
... ...
package com.zhonglai.socket.html.http;
import com.zhonglai.socket.html.http.handler.HttpServerInboundHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import javax.net.ssl.SSLEngine;
public class HttpChannelInitService extends ChannelInitializer<SocketChannel> {
private HttpServerInboundHandler httpServerInboundHandler = null;
private SslContext sslContext = null;
public HttpChannelInitService(HttpServerInboundHandler httpServerInboundHandler)
{
this.httpServerInboundHandler = httpServerInboundHandler;
}
public HttpChannelInitService(HttpServerInboundHandler httpServerInboundHandler, SslContext sslContext)
{
this.sslContext = sslContext;
this.httpServerInboundHandler = httpServerInboundHandler;
}
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if(null != sslContext) //https
{
SSLEngine engine = sslContext.newEngine(ch.alloc());
pipeline.addFirst("ssl", new SslHandler(engine));
}
pipeline.addLast("http-decoder",
new HttpRequestDecoder());
pipeline.addLast("http-aggregator",
new HttpObjectAggregator(65536));
pipeline.addLast("http-encoder",
new HttpResponseEncoder());
pipeline.addLast("http-chunked",
new ChunkedWriteHandler());
pipeline.addLast("httpServerHandler",httpServerInboundHandler
);
}
}
... ...
package com.zhonglai.socket.html.http.handler;
import com.zhonglai.socket.html.http.service.AnalysisService;
import com.zhonglai.socket.html.http.service.impl.DefaultAnalysisServiceImpl;
import com.zhonglai.socket.html.http.util.HttpResponseUtil;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import static io.netty.handler.codec.http.HttpMethod.GET;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
@ChannelHandler.Sharable
public class HttpServerInboundHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
AnalysisService analysisService = new DefaultAnalysisServiceImpl();
public HttpServerInboundHandler(AnalysisService analysisService)
{
this.analysisService = analysisService;
}
public HttpServerInboundHandler()
{
}
protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
if (!request.decoderResult().isSuccess()) {
sendError(ctx, BAD_REQUEST);
return;
}
if (request.method() != GET) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
final String uri = request.uri();
System.out.println("come here messageReceived uri="+uri);
//这里可以根据具体的url来拆分,获取请求带过来的参数,实现自己具体的业务操作
analysisService.analysis(ctx,request);
//sendError(ctx, UNAUTHORIZED);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
if (ctx.channel().isActive()) {
sendError(ctx, INTERNAL_SERVER_ERROR);
}
}
private static void sendError(ChannelHandlerContext ctx,
HttpResponseStatus status) {
ctx.writeAndFlush(HttpResponseUtil.newERResponse(status)).addListener(ChannelFutureListener.CLOSE);
}
}
... ...
package com.zhonglai.socket.html.http.service;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
public interface AnalysisService {
public void analysis(ChannelHandlerContext ctx, FullHttpRequest request);
}
... ...
package com.zhonglai.socket.html.http.service.impl;
import com.zhonglai.socket.html.http.service.AnalysisService;
import com.zhonglai.socket.html.http.util.HttpResponseUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
public class DefaultAnalysisServiceImpl implements AnalysisService {
public void analysis(ChannelHandlerContext ctx, FullHttpRequest request) {
HttpResponseUtil.sendOkMessage(ctx,"http请求成功!");
}
}
... ...
package com.zhonglai.socket.html.http.service.impl;
import com.google.gson.JsonObject;
import com.zhonglai.dto.Message;
import com.zhonglai.dto.MessageCode;
import com.zhonglai.socket.html.action.Base;
import com.zhonglai.socket.html.http.service.AnalysisService;
import com.zhonglai.socket.html.http.util.HttpResponseUtil;
import com.zhonglai.socket.html.http.util.ParameterAnalysisUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Set;
/**
* 解析2个路径协议的业务
*/
public class Path2AnalysisServiceImpl implements AnalysisService {
String actionPath = "";
public Path2AnalysisServiceImpl( String actionPath )
{
this.actionPath = actionPath;
}
public void analysis(ChannelHandlerContext ctx, FullHttpRequest request) {
String uri = request.uri();
String path = ParameterAnalysisUtil.UrlPage(uri);
if(StringUtils.isNoneBlank(path))
{
String[] paths = path.split("/");
if(paths.length==3)
{
String clasPath = actionPath + "."+paths[1].substring(0, 1).toUpperCase() + paths[1].substring(1)+"Action";
String name = paths[2];
System.out.println("解析到执行方法路径:"+clasPath+" 执行方法名称"+name);
JsonObject parameter = ParameterAnalysisUtil.URLRequestJson(uri); //获取url参数
if(null == parameter)
{
parameter = new JsonObject();
}
Set set = request.headers().names();
Iterator it = set.iterator();
while(it.hasNext()){//遍历 获取head参数
Object object = it.next();
if(object instanceof String)
{
String key = (String) object;
parameter.addProperty(key,request.headers().get(key)+"");
}
}
Class<?> cls = null; // 取得Class对象
try {
cls = Class.forName(clasPath);
Object obj = cls.newInstance(); //反射实例化对象
Base base = (Base) obj;
base.setParameter(parameter);//先设置参数
Method m = cls.getDeclaredMethod(name);
Message message = (Message) m.invoke(obj); //执行方法
HttpResponseUtil.sendOkMessage(ctx,message); //返回
return;
} catch (ClassNotFoundException e) {
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"没有找到这个方法"+clasPath));
return;
} catch (IllegalAccessException e) {
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"方法类实例失败"+clasPath));
return;
} catch (InstantiationException e) {
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"方法类实例失败"+clasPath));
return;
} catch (NoSuchMethodException e) {
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"方法获取失败"+clasPath+" "+name));
return;
} catch (InvocationTargetException e) {
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"方法执行失败"+clasPath+" "+name));
return;
}
}
}
HttpResponseUtil.sendOkMessage(ctx,new Message(MessageCode.DEFAULT_FAIL_CODE,"方法规则不符合协议规则"));
}
}
... ...
package com.zhonglai.socket.html.http.util;
import com.zhonglai.dto.Message;
import com.zhonglai.serialization.GsonConstructor;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
/**
* 返回操作工具
*/
public class HttpResponseUtil {
/**
* 成功返回消息
* @param ctx
* @param txt
*/
public static void sendOkString(ChannelHandlerContext ctx, String txt)
{
FullHttpResponse response = newOKResponse();
StringBuilder buf = new StringBuilder();
buf.append(txt);
ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);
response.content().writeBytes(buffer);
buffer.release();
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
/**
* 成功返回消息
* @param ctx
* @param message
*/
public static void sendOkMessage(ChannelHandlerContext ctx,Message message)
{
sendOkString(ctx, GsonConstructor.get().toJson(message));
}
/**
* 成功返回
* @return
*/
public static FullHttpResponse newOKResponse()
{
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
return response;
}
/**
* 错误返回
* @param status
* @return
*/
public static FullHttpResponse newERResponse(HttpResponseStatus status)
{
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,
status, Unpooled.copiedBuffer("Failure: " + status.toString()
+ "\r\n", CharsetUtil.UTF_8));
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
return response;
}
}
... ...
package com.zhonglai.socket.html.http.util;
import com.google.gson.JsonObject;
import java.util.HashMap;
import java.util.Map;
/**
* 参数解析工具
*/
public class ParameterAnalysisUtil {
/**
* 解析出url请求的路径,包括页面
* @param strURL url地址
* @return url路径
*/
public static String UrlPage(String strURL)
{
String strPage=null;
String[] arrSplit=null;
// strURL=strURL.trim().toLowerCase();
arrSplit=strURL.split("[?]");
if(strURL.length()>0)
{
if(arrSplit.length>=1)
{
if(arrSplit[0]!=null)
{
strPage=arrSplit[0];
}
}
}
return strPage;
}
/**
* 去掉url中的路径,留下请求参数部分
* @param strURL url地址
* @return url请求参数部分
*/
private static String TruncateUrlPage(String strURL)
{
String strAllParam=null;
String[] arrSplit=null;
strURL=strURL.trim().toLowerCase();
arrSplit=strURL.split("[?]");
if(strURL.length()>1)
{
if(arrSplit.length>1)
{
if(arrSplit[1]!=null)
{
strAllParam=arrSplit[1];
}
}
}
return strAllParam;
}
/**
* 解析出url参数中的键值对
* 如 "index.jsp?Action=del&id=123",解析出Action:del,id:123存入map中
* @param URL url地址
* @return url请求参数部分
*/
public static Map<String, String> URLRequestMap(String URL)
{
Map<String, String> mapRequest = new HashMap<String, String>();
String[] arrSplit=null;
String strUrlParam=TruncateUrlPage(URL);
if(strUrlParam==null)
{
return mapRequest;
}
//每个键值为一组 www.2cto.com
arrSplit=strUrlParam.split("[&]");
for(String strSplit:arrSplit)
{
String[] arrSplitEqual=null;
arrSplitEqual= strSplit.split("[=]");
//解析出键值
if(arrSplitEqual.length>1)
{
//正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
}
else
{
if(arrSplitEqual[0]!="")
{
//只有参数没有值,不加入
mapRequest.put(arrSplitEqual[0], "");
}
}
}
return mapRequest;
}
/**
* 解析出url参数中的键值对
* 如 "index.jsp?Action=del&id=123",解析出Action:del,id:123存入map中
* @param URL url地址
* @return url请求参数部分
*/
public static JsonObject URLRequestJson(String URL)
{
JsonObject jsonObject = new JsonObject();
String[] arrSplit=null;
String strUrlParam=TruncateUrlPage(URL);
if(strUrlParam==null)
{
return jsonObject;
}
//每个键值为一组 www.2cto.com
arrSplit=strUrlParam.split("[&]");
for(String strSplit:arrSplit)
{
String[] arrSplitEqual=null;
arrSplitEqual= strSplit.split("[=]");
//解析出键值
if(arrSplitEqual.length>1)
{
//正确解析
jsonObject.addProperty(arrSplitEqual[0], arrSplitEqual[1]);
}
else
{
if(arrSplitEqual[0]!="")
{
//只有参数没有值,不加入
jsonObject.addProperty(arrSplitEqual[0], "");
}
}
}
return jsonObject;
}
}
... ...