在Android中使用netty可以很容易搭建一个web服务器;同时具有netty的优良特性:高性能,高可靠性,API易上手等;本篇文章主要介绍在Android中使用netty搭建web服务器的简单过程,对于一些复杂使用,复杂特性不做深究;不甚了解netty的可以先阅读此篇入门文章:Netty在Android中使用

  • 目录
  • 1.服务器配置及启动
  • 2.实现客户端请求数据的读取:HttpServerHandler
  • 3.实现数据发送
  • 4.注意地方
  • 5.推荐阅读

1.服务器配置及启动

  • 在后台线程中执行此方法:
private void startServer() {        try {            EventLoopGroup bossGroup = new NioEventLoopGroup();            EventLoopGroup workerGroup = new NioEventLoopGroup();            ServerBootstrap b = new ServerBootstrap();            b.group(bossGroup, workerGroup)                    .channel(NioServerSocketChannel.class)                    .childHandler(new ChannelInitializer() {                        @Override                        protected void initChannel(io.netty.channel.socket.SocketChannel socketChannel) throws Exception {                            ChannelPipeline pipeline = socketChannel.pipeline();                            // http服务器端对request解码                            pipeline.addLast(new HttpRequestDecoder());                            // http服务器端对response编码                            pipeline.addLast(new HttpResponseEncoder());                            // 在处理POST消息体时需要加上                            pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));                            // 处理发起的请求                               pipeline.addLast(new HttpServerHandler());                            //在HttpResponseEncoder序列化之前会对response对象进行HttpContentCompressor压缩                            pipeline.addLast("compressor", new HttpContentCompressor());                        }                    });            b.bind(new InetSocketAddress(PORT)).sync();            Log.d(TAG, "HTTP服务启动成功 PORT=" + PORT);        } catch (Exception e) {            e.printStackTrace();        }    }
  • 使用Http进行编解码主要添加:
// http服务器端对request解码pipeline.addLast(new HttpRequestDecoder());// http服务器端对response编码pipeline.addLast(new HttpResponseEncoder());
  • 对发起的请求进行处理:(详细见#2中的实现方法)
pipeline.addLast(new HttpServerHandler());

2.实现客户端请求数据的读取:HttpServerHandler

  • 详细步骤见代码
  • 浏览器访问参考:

http://172.16.3.112:8080/json
http://172.16.3.112:8080/login?name=admin&psw=123456
http://172.16.3.112:8080/getImage

package me.com.testnettywebserver;import android.net.Uri;import android.util.Log;import org.json.JSONException;import org.json.JSONObject;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.codec.http.DefaultFullHttpResponse;import io.netty.handler.codec.http.FullHttpRequest;import io.netty.handler.codec.http.FullHttpResponse;import io.netty.handler.codec.http.HttpHeaderNames;import io.netty.handler.codec.http.HttpMethod;import io.netty.handler.codec.http.HttpObject;import io.netty.handler.codec.http.HttpResponseStatus;import io.netty.handler.codec.http.HttpVersion;import io.netty.util.CharsetUtil;public class HttpServerHandler extends SimpleChannelInboundHandler {    private static final String TAG = "HttpServerHandler";    @Override    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {        if (!(msg instanceof FullHttpRequest)){            Log.e(TAG,"未知请求:"+msg.toString());            return;        }        FullHttpRequest httpRequest = (FullHttpRequest) msg;        String path = httpRequest.uri();        HttpMethod method = httpRequest.method();        String route = parseRoute(path);        Map params = new HashMap<>();        if (method == HttpMethod.GET){            parseGetParams(params,path);        }else if (method == HttpMethod.POST){            parsePostParams(params,httpRequest);        }else {            ByteBuf byteBuf = Unpooled.copiedBuffer(HttpResult.error("不支持的请求方式").getBytes());            response(ctx,"text/json;charset=UTF-8",byteBuf, HttpResponseStatus.BAD_REQUEST);        }        Log.e(TAG,"******************接收到了请求******************");        Log.e(TAG,"method:"+method);        Log.e(TAG,"route:"+route);        Log.e(TAG,"params:"+params.toString());        //路由实现        handlerRequest(ctx,route,params);    }    private void handlerRequest(ChannelHandlerContext ctx, String route, Map params) {        switch (route){            case "login":                ByteBuf login;                if ("admin".equals(params.get("name")) && "123456".equals(params.get("psw"))){                    login = Unpooled.copiedBuffer(HttpResult.ok("登录成功").getBytes());                }else {                    login = Unpooled.copiedBuffer(HttpResult.error("登录失败").getBytes());                }                response(ctx,"text/json;charset=UTF-8",login,HttpResponseStatus.OK);                break;            case "getImage":                ByteBuf imgBuf = getImage(new File("/storage/emulated/0/MagazineUnlock/1.jpg"));                response(ctx,"image/jpeg",imgBuf,HttpResponseStatus.OK);                break;            case "json":                ByteBuf byteBuf = Unpooled.copiedBuffer(HttpResult.ok("测试post请求成功").getBytes());                response(ctx,"text/json;charset=UTF-8",byteBuf,HttpResponseStatus.OK);                break;            default:                ByteBuf buf = Unpooled.copiedBuffer(HttpResult.error("未实现的请求地址").getBytes());                response(ctx,"text/json;charset=UTF-8",buf,HttpResponseStatus.BAD_REQUEST);                break;        }    }    private ByteBuf getImage(File file) {        ByteBuf byteBuf = Unpooled.buffer();        try {            FileInputStream fileInputStream = new FileInputStream(file);            int len;            byte[] buf = new byte[1024];            while ((len = fileInputStream.read(buf)) != -1){                byteBuf.writeBytes(buf,0,len);            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return byteBuf;    }    private void parsePostParams(Map params, FullHttpRequest httpRequest) {        ByteBuf content = httpRequest.content();        String body = content.toString(CharsetUtil.UTF_8);        try {            JSONObject jsonObject = new JSONObject(body);            Iterator iterator = jsonObject.keys();            while (iterator.hasNext()){                String key = iterator.next();                params.put(key,jsonObject.opt(key));            }        } catch (JSONException e) {            e.printStackTrace();        }    }    private void parseGetParams(Map params, String path) {        Uri uri = Uri.parse("http://172.16.0.1"+path);        Set names = uri.getQueryParameterNames();        Iterator iterator = names.iterator();        while (iterator.hasNext()){            String key = iterator.next();            params.put(key,uri.getQueryParameter(key));        }    }    private void response(ChannelHandlerContext ctx, String type, ByteBuf byteBuf, HttpResponseStatus status) {        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,status,byteBuf);        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,type);        ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);    }    /**     * 解析调用的接口(路由地址)     */    private String parseRoute(String path) {        if (path.contains("?")) {            String uri = path.split("\\?")[0];            return uri.substring(1);        } else {            return path.substring(1);        }    }}

3.实现数据发送

private void response(ChannelHandlerContext ctx, String type, ByteBuf byteBuf, HttpResponseStatus status) {        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,status,byteBuf);        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,type);        ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);    }

4.注意地方

  • 添加权限
            
  • 跨域解决(跨域原因是:浏览器的同源策略,前端使用了不同源的url访问服务器)
    解决方法:在Response header中添加:
httpResponse.headers().add("Access-Control-Allow-Origin", "*");httpResponse.headers().add("Access-Control-Allow-Methods", "GET, POST, PUT,DELETE,OPTIONS,PATCH");httpResponse.headers().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");

5.推荐阅读

  • Netty在Android中的常见使用
  • 在Android中使用Netty接收Http文件上传

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. 箭头函数的基础使用
  3. NPM 和webpack 的基础使用
  4. Python list sort方法的具体使用
  5. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  6. python list.sort()根据多个关键字排序的方法实现
  7. android EditText设置不可写
  8. Android(安卓)拨号器的简单实现
  9. android 使用html5作布局文件: webview跟javascript交互

随机推荐

  1. 实例演示模态框
  2. CSS中盒模型属性、常用单位以及媒体查询
  3. php设计模式之模板模式实例分析【星际争
  4. q版人物怎么画?q版漫画人物绘画教程
  5. 登录表单、简单后台架构、演示元素样式来
  6. 模态框简单编写
  7. 视口、定位和模态框
  8. android pull解析
  9. Android日历(Calendar,dataPicker)
  10. 浅谈android的selector背景选择器