Netty(4)HTTP服务

前言

前面写了一个TCP服务的案例
Netty也可以完成HTTP服务

目录

  1. HTTP服务案例
  2. 存在的问题
  3. 过滤资源
  4. 特有的Pipeline和handler

HTTP服务案例

要求:打开端口9999,服务器建立连接,发送hello

服务器

package Netty.Http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TestServer {
    public static void main(String[] args) throws Exception{
        //两个线程池
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        try{
            //ServerBootstrap
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //配置参数
            serverBootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new TestServerInit());//将设置的类放入

            ChannelFuture channelFuture = serverBootstrap.bind(9999);

            channelFuture.channel().closeFuture().sync();

        }finally {
            //关闭线程池
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

其中与自定义了一个TestServerInit类,用于放置多个管道处理器

TestServerInit

package Netty.Http;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

public class TestServerInit extends ChannelInitializer<SocketChannel> {

    protected void initChannel(SocketChannel ch) throws Exception {
        //向管道加入处理器

        //得到管道
        ChannelPipeline pipeline = ch.pipeline();

        //加入netty提供的httpServerCodec  codec=>[coder - decoder]
        //HttpServerCodec是netty提供的编解码器
        pipeline.addLast("MyTestHTTPCodec",new HttpServerCodec());
        //增加一个自定义的handler
        pipeline.addLast("MyTestHttpServerHandler",new TestHttpServerHandler());
    }
}

自定义处理器:TestHttpServerHandler

package Netty.Http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.net.URI;

/*
自定义管道处理器的另一种写法:SimpleChannelInboundHandler
SimpleChannelInboundHandler是ChannelInboundHandlerAdapter的子类,方法更多
HttpObject 客户端和服务器通讯的数据封装成HttpObject
*/


public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    //读取客户端数据
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //判断msg 是不是 httpRequest请求
        if (msg instanceof HttpRequest){

            System.out.println("msg类型 = "+msg.getClass());
            System.out.println("客户端地址 :"+ctx.channel().remoteAddress());
            
            //回复信息给浏览器[http协议信息]

            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_8);
            //构造一http的响应,HttpResponse
            //设置响应头信息:版本+状态码+内容
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
          
            //长度
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //将构建好的响应信息返回
            ctx.writeAndFlush(response);
        }
    }
}

火狐浏览器打开:http://localhost:9999/
在这里插入图片描述
在这里插入图片描述

存在的问题

令人头大的中文乱码

在这里插入图片描述
响应的中文是正确的格式,在浏览器运行就出问题了,可以确定是浏览器显示的问题

火狐浏览器处理方法:
先在页面按Alt键:
在这里插入图片描述
查看 -》 文字编码 -》选择Unicode(默认是西文,编码格式不相同会乱码)

解决
在这里插入图片描述
但是肯定不能总是让客户端设置编码
我们可以在服务器端设置好客户端的编码方式,设置响应头HttpHeaderNames.CONTENT_TYPE

//设置响应头信息:返回类型CONTENT_TYPE
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/html; charset=UTF-8");

在这里插入图片描述
设置浏览器的编码格式

在这里插入图片描述

两个请求

在这里插入图片描述
这是网页图标请求,可以用过滤方法过滤资源

过滤资源

在TestHttpServerHandler类中,可以根据URI资源标识将该请求过滤

package Netty.Http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.net.URI;

/*
自定义管道的另一种写法:SimpleChannelInboundHandler
SimpleChannelInboundHandler是ChannelInboundHandlerAdapter的子类,方法更多
HttpObject 客户端和服务器通讯的数据封装成HttpObject
*/


public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    //读取客户端数据
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //判断msg 是不是 httpRequest请求
        if (msg instanceof HttpRequest){

            System.out.println("msg类型 = "+msg.getClass());
            System.out.println("客户端地址 :"+ctx.channel().remoteAddress());
            //过滤信息
            HttpRequest httpRequest = (HttpRequest) msg;
            //获取URI资源标识符,过滤指定值
            URI uri = new URI(httpRequest.uri());
            if ("/favicon.ico".equals(uri.getPath())){
                System.out.println("请求了favicon.ico资源,不做响应");
                return;
            }
            //回复信息给浏览器[http协议信息]

            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_8);
            //构造一http的响应,HttpResponse
            //设置响应头信息:版本+状态码+内容
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            //设置响应头信息:返回类型CONTENT_TYPE
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain;CharsetUtil.UTF_8");
            //长度
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //将构建好的响应信息返回
            ctx.writeAndFlush(response);
        }
    }
}

在这里插入图片描述
请求网址是http://localhost:9999/favicon.ico
用URI获得请求标识,根据网址过滤掉
在这里插入图片描述

特有的Pipeline和handler

前面学习Netty模型知道了pipeline中的handler是负责处理业务的对象

对于多个业务,会创建多个pipeline和handler

在TestHttpServerHandler类中的channelRead0方法加上:

System.out.println("PipeLine hashCode :"+ctx.channel().pipeline().hashCode());
System.out.println("handler hashCode :"+this.hashCode());

在这里插入图片描述
针对一个浏览器请求,会创建pipeline和handler处理业务
再来一个浏览器请求:
在这里插入图片描述
pipeline和handler是不同的

刷新网页,pipeline和handler也会重新创建
HTTP1.1以前是短连接
在这里插入图片描述

在HTTP1.1已经改成了默认长连接
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值