Netty4實現HTTP請求、響應
阿新 • • 發佈:2018-12-10
前言:
我們所編寫的專案多以BS為主,使用者通過瀏覽器訪問我們的伺服器
傳送的請求以HTTP請求為主,本例就以Netty4來實現一個接收HTTP請求的伺服器,並根據使用者請求返回響應
1.Netty中HTTP請求和響應類
- 請求(FullHttpRequest)
/** * Combine the {@link HttpRequest} and {@link FullHttpMessage}, so the request is a <i>complete</i> HTTP * request. */ public interface FullHttpRequest extends HttpRequest, FullHttpMessage {
可以看到,它結合了HttpRequest、FullHttpMessag,作為一個完整的HTTP請求體。
預設實現為DefaultFullHttpRequest
- 響應(FullHttpResponse)
/** * Combination of a {@link HttpResponse} and {@link FullHttpMessage}. * So it represent a <i>complete</i> http response. */ public interface FullHttpResponse extends HttpResponse, FullHttpMessage {
同樣,它結合了HttpResponse、FullHttpMessage
預設實現為DefaultFullHttpResponse
*
2.Netty中客戶端、服務端的編解碼器
作為服務端而言:
主要工作就是接收客戶端請求,將客戶端的請求內容解碼;傳送響應給客戶端,並將傳送內容編碼
所以,服務端需要兩個編解碼器
* HttpRequestDecoder(將請求內容解碼)
* HttpResponseEncoder(將響應內容編碼)
作為客戶端而言:
主要工作就是傳送請求給服務端,並將傳送內容編碼;接收服務端響應,並將接收內容解碼;
所以,客戶端需要兩個編解碼器
* HttpResponseDecoder(將響應內容解碼)
* HttpRequestEncoder(將請求內容編碼)
3.Server端編寫Handler類處理客戶請求
建立Handler,命名為HttpHandler,具體內容如下:
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.根據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.設定響應
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.傳送
// 注意必須在使用完之後,close channel
ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
}
}
@Data
class Content{
String uri;
String content;
}
注意:
在處理過程中,把msg轉換為FullHttpRequest,可以獲取關於請求的所有內容;
在傳送響應時必須要監聽CLOSE
*
4.測試
- 啟動Server類
- 使用客戶端傳送請求
在這裡,筆者不單獨編寫Netty客戶端程式碼,直接使用PostMan來充當客戶端傳送請求,具體如下:
傳送一個post請求,並填寫body,點選send,可以看到響應如下所示:
參考:Netty in Action