Netty4之如何實現(xiàn)HTTP請求、響應(yīng)
前言
我們所編寫的項目多以BS為主,用戶通過瀏覽器訪問我們的服務(wù)器
發(fā)送的請求以HTTP請求為主,本例就以Netty4來實現(xiàn)一個接收HTTP請求的服務(wù)器,并根據(jù)用戶請求返回響應(yīng)
1.Netty中HTTP請求和響應(yīng)類
請求(FullHttpRequest)
/**
* Combine the {@link HttpRequest} and {@link FullHttpMessage}, so the request is a <i>complete</i> HTTP
* request.
*/
public interface FullHttpRequest extends HttpRequest, FullHttpMessage {
可以看到,它結(jié)合了HttpRequest、FullHttpMessag,作為一個完整的HTTP請求體。
默認實現(xiàn)為DefaultFullHttpRequest
響應(yīng)(FullHttpResponse)
/**
* Combination of a {@link HttpResponse} and {@link FullHttpMessage}.
* So it represent a <i>complete</i> http response.
*/
public interface FullHttpResponse extends HttpResponse, FullHttpMessage {
同樣,它結(jié)合了HttpResponse、FullHttpMessage
默認實現(xiàn)為DefaultFullHttpResponse
*
2.Netty中客戶端、服務(wù)端的編解碼器
作為服務(wù)端而言:
主要工作就是接收客戶端請求,將客戶端的請求內(nèi)容解碼;發(fā)送響應(yīng)給客戶端,并將發(fā)送內(nèi)容編碼
所以,服務(wù)端需要兩個編解碼器
* HttpRequestDecoder(將請求內(nèi)容解碼)
* HttpResponseEncoder(將響應(yīng)內(nèi)容編碼)
作為客戶端而言:
主要工作就是發(fā)送請求給服務(wù)端,并將發(fā)送內(nèi)容編碼;接收服務(wù)端響應(yīng),并將接收內(nèi)容解碼;
所以,客戶端需要兩個編解碼器
* HttpResponseDecoder(將響應(yīng)內(nèi)容解碼)
* HttpRequestEncoder(將請求內(nèi)容編碼)
3.Server端編寫Handler類處理客戶請求
創(chuàng)建Handler,命名為HttpHandler,具體內(nèi)容如下:
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
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.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import lombok.Data;
/**
* 處理HTTP請求
* @author Administrator
*
*/
public class HttpHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if(msg instanceof FullHttpRequest){
FullHttpRequest req = (FullHttpRequest)msg;
try {
// 1.獲取URI
String uri = req.uri();
// 2.獲取請求體
ByteBuf buf = req.content();
String content = buf.toString(CharsetUtil.UTF_8);
// 3.獲取請求方法
HttpMethod method = req.method();
// 4.獲取請求頭
HttpHeaders headers = req.headers();
// 5.根據(jù)method,確定不同的邏輯
if(method.equals(HttpMethod.GET)){
// TODO
}
if(method.equals(HttpMethod.POST)){
// 接收用戶輸入,并將輸入返回給用戶
Content c = new Content();
c.setUri(uri);
c.setContent(content);
response(ctx, c);
}
if(method.equals(HttpMethod.PUT)){
// TODO
}
if(method.equals(HttpMethod.DELETE)){
// TODO
}
} finally {
req.release();
}
}
}
private void response(ChannelHandlerContext ctx, Content c) {
// 1.設(shè)置響應(yīng)
FullHttpResponse resp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.copiedBuffer(JSONObject.toJSONString(c), CharsetUtil.UTF_8));
resp.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
// 2.發(fā)送
// 注意必須在使用完之后,close channel
ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
}
}
@Data
class Content{
String uri;
String content;
}
注意:
在處理過程中,把msg轉(zhuǎn)換為FullHttpRequest,可以獲取關(guān)于請求的所有內(nèi)容;
在發(fā)送響應(yīng)時必須要監(jiān)聽CLOSE
*
4.測試
啟動Server類使用客戶端發(fā)送請求
在這里,筆者不單獨編寫Netty客戶端代碼,直接使用PostMan來充當客戶端發(fā)送請求,具體如下:

發(fā)送一個post請求,并填寫body,點擊send,可以看到響應(yīng)如下所示:

參考:Netty in Action
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring系統(tǒng)屬性及spring.properties配置文件示例詳解
spring中有一個SpringProperties類,來保存spring的系統(tǒng)屬性,本文結(jié)合實例代碼對Spring系統(tǒng)屬性及spring.properties配置文件相關(guān)知識給大家介紹的非常詳細,需要的朋友參考下吧2023-07-07
詳解jenkins自動部署springboot應(yīng)用的方法
這篇文章主要介紹了詳解jenkins自動部署springboot應(yīng)用的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
SpringBoot項目中application.yml和bootstrap.yml文件的區(qū)別及說明
`application.yml`和`bootstrap.yml`都是Spring Boot項目中的配置文件,但它們在加載時機、用途、優(yōu)先級、配置來源、適用場景和是否必須存在等方面存在區(qū)別2025-03-03

