netty整合springMVC,實現高效的HTTP服務請求
參考http://blog.csdn.net/imlsz/article/details/42673507的程式碼,謝謝!不過在處理返回servlet的結果時候,按照上文的方法不行。
首先,你必須要了解netty,說簡單點:客戶端通過TCP連結和伺服器建立長連線,client和server都是通過管道(ChannelPipeline)的addLast方法的新增順序來處理接收或者傳送的資料。這個和struts的filter的doFilter原理類似,處理完一個filter,如果後面還有其他的filter,就將資料chain.doFilter來繼續處理。
然後,說說netty怎麼來整合springMVC:當client和server建立連線後,我們在addLast的某個類中將client發來的請求,讓DispatcherServlet來處理,然後將處理後的結果通過ChannelHandlerContext或者Channel將,結果writeAndFlush到client。
1.寫一個netty sever的java程式碼
package com.magic.netty.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.DispatcherServlet;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import com.magic.netty.HttpServerInitializer;
public class NettyHttpServer {
public NettyHttpServer(Integer port) {
this.port = port;
}
public NettyHttpServer (Integer port, DispatcherServlet servlet) {
this.port = port;
this.servlet = servlet;
}
public void start(){
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new HttpServerInitializer(servlet))
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
System.out.println("NettyHttpServer Run successfully");
// 繫結埠,開始接收進來的連線
ChannelFuture f = b.bind(port).sync();
// 等待伺服器 socket 關閉 。在這個例子中,這不會發生,但你可以優雅地關閉你的伺服器。
f.channel().closeFuture().sync();
} catch (Exception e) {
log.error("NettySever start fail",e);
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
private int port;
private static Logger log = LoggerFactory.getLogger(NettyHttpServer.class);
private DispatcherServlet servlet;
}
2.初始化netty的channel管道
package com.magic.netty;
import org.springframework.web.servlet.DispatcherServlet;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
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.stream.ChunkedWriteHandler;
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {
public HttpServerInitializer(DispatcherServlet servlet) {
this.servlet = servlet;
}
public HttpServerInitializer() {
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("aggregator", new HttpObjectAggregator(2147483647));
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
pipeline.addLast("deflater", new HttpContentCompressor());
pipeline.addLast("handler", new HttpRequestHandler(servlet));
}
private DispatcherServlet servlet;
}
3.在handler裡面處理client發來的請求
package com.magic.netty;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletContext;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import io.netty.handler.codec.http.multipart.MemoryAttribute;
import io.netty.util.CharsetUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
public HttpRequestHandler(DispatcherServlet servlet) {
this.servlet = servlet;
this.servletContext = servlet.getServletConfig().getServletContext();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
logger.error(e.getMessage(),e);
ctx.close();
}
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
boolean flag = HttpMethod.POST.equals(fullHttpRequest.getMethod())
|| HttpMethod.GET.equals(fullHttpRequest.getMethod());
Map<String, String> parammap = getRequestParams(ctx,fullHttpRequest);
if(flag && ctx.channel().isActive()){
//HTTP請求、GET/POST
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
MockHttpServletRequest servletRequest =new MockHttpServletRequest(servletContext);
// headers
for (String name : fullHttpRequest.headers().names()) {
for (String value : fullHttpRequest.headers().getAll(name)) {
servletRequest.addHeader(name, value);
}
}
String uri = fullHttpRequest.getUri();
uri = new String(uri.getBytes("ISO8859-1"), "UTF-8");
uri = URLDecoder.decode(uri, "UTF-8");
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).build();
String path = uriComponents.getPath();
path = URLDecoder.decode(path, "UTF-8");
servletRequest.setRequestURI(path);
servletRequest.setServletPath(path);
servletRequest.setMethod(fullHttpRequest.getMethod().name());
if (uriComponents.getScheme() != null) {
servletRequest.setScheme(uriComponents.getScheme());
}
if (uriComponents.getHost() != null) {
servletRequest.setServerName(uriComponents.getHost());
}
if (uriComponents.getPort() != -1) {
servletRequest.setServerPort(uriComponents.getPort());
}
ByteBuf content = fullHttpRequest.content();
content.readerIndex(0);
byte[] data = new byte[content.readableBytes()];
content.readBytes(data);
servletRequest.setContent(data);
try {
if (uriComponents.getQuery() != null) {
String query = UriUtils.decode(uriComponents.getQuery(),"UTF-8");
servletRequest.setQueryString(query);
}
if(parammap!=null&¶mmap.size()>0){
for (String key : parammap.keySet()) {
servletRequest.addParameter(UriUtils.decode(key,"UTF-8"), UriUtils.decode(parammap.get(key) == null ? "": parammap.get(key), "UTF-8"));
}
}
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
this.servlet.service(servletRequest,servletResponse);
HttpResponseStatus status = HttpResponseStatus.valueOf(servletResponse.getStatus());
String result = servletResponse.getContentAsString();
result = StringUtils.isEmpty(result)?"":result;
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,Unpooled.copiedBuffer(result,CharsetUtil.UTF_8));
response.headers().set("Content-Type", "text/json;charset=UTF-8");
response.headers().set("Access-Control-Allow-Origin", "*");
response.headers().set("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,X-File-Name");
response.headers().set("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
response.headers().set("Content-Length", Integer.valueOf(response.content().readableBytes()));
response.headers().set("Connection", "keep-alive");
ChannelFuture writeFuture = ctx.writeAndFlush(response);
writeFuture.addListener(ChannelFutureListener.CLOSE);
}
}
/**
* 獲取post請求、get請求的引數儲存到map中
*/
private Map<String, String> getRequestParams(ChannelHandlerContext ctx, HttpRequest req){
Map<String, String>requestParams=new HashMap<String, String>();
// 處理get請求
if (req.getMethod() == HttpMethod.GET) {
QueryStringDecoder decoder = new QueryStringDecoder(req.getUri());
Map<String, List<String>> parame = decoder.parameters();
Iterator<Entry<String, List<String>>> iterator = parame.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, List<String>> next = iterator.next();
requestParams.put(next.getKey(), next.getValue().get(0));
}
}
// 處理POST請求
if (req.getMethod() == HttpMethod.POST) {
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(
new DefaultHttpDataFactory(false), req);
List<InterfaceHttpData> postData = decoder.getBodyHttpDatas(); //
for(InterfaceHttpData data:postData){
if (data.getHttpDataType() == HttpDataType.Attribute) {
MemoryAttribute attribute = (MemoryAttribute) data;
requestParams.put(attribute.getName(), attribute.getValue());
}
}
}
return requestParams;
}
private static final Logger logger = LoggerFactory.getLogger(HttpRequestHandler.class);
private final DispatcherServlet servlet;
private final ServletContext servletContext;
}
4.初始化servlet並啟動netty server
package com.magic;
import javax.servlet.ServletException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import com.magic.common.config.PropConfig;
import com.magic.netty.server.NettyHttpServer;
public class MagicWebServer {
private static Logger logger = LoggerFactory.getLogger(MagicWebServer.class
相關推薦
netty整合springMVC,實現高效的HTTP服務請求
參考http://blog.csdn.net/imlsz/article/details/42673507的程式碼,謝謝!不過在處理返回servlet的結果時候,按照上文的方法不行。
首先,你必須要了解netty,說簡單點:客戶端通過TCP連結和伺服器建立長連線
Zuul中整合Swagger2,實現對源服務API測試
前言
我們知道,Swagger2整合到專案中,可以非常方便地進行介面測試,是前後端對接效率提高。現在,我們可以在Zuul中整合Swagger2,通過Zuul配置檔案配置的對映路徑,來生成源服務介面的測
Shiro 整合SpringMVC 並且實現許可權管理,登入和登出
Apache Shiro是Java的一個安全框架。目前,使用Apache Shiro的人越來越多,因為它相當簡單,對比Spring Security,可能沒有Spring Security做的功能強大,但是在實際工作時可能並不需要那麼複雜的東西,所以使用小而簡單
SpringMVC整合quartz,實現定時任務
首先,我用的是maven下載jar包
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artif
SpringBoot2 高階案例(14) : 整合 Drools規則引擎,實現高效的業務規則
一、Drools引擎簡介
1、基礎簡介
Drools是一個基於java的規則引擎,開源的,可以將複雜多變的規則從硬編碼中解放出來,以規則指令碼的形式存放在檔案中,使得規則的變更不需要修正程式碼重啟機器就可以立即在線上環境生效。具有易於訪問企業策略、易於調整以及易於管理的特點,作為開源業務規則引擎,符合業內
Spring(五):Spring&Struts2&Hibernate整合後,實現查詢Employee信息
view event last .html ssh tla url 配置文件 hid
背景:
基於之前兩篇文章《Spring(三):Spring整合Hibernate》、《Spring(四):Spring整合Hibernate,之後整合Struts2》,了解了
Spring Boot 整合 Elasticsearch,實現 function score query 權重分查詢
search 小寫 業務 jpg 啟動會 last cti cal agen 摘要: 原創出處 www.bysocket.com 「泥瓦匠BYSocket 」歡迎轉載,保留摘要,謝謝!
『 預見未來最好的方式就是親手創造未來 – 《史蒂夫·喬布斯
jmeter通過BeanShell 腳本,實現對http請求參數的加密
一個 sha 下載源碼 功能 mage 使用 1-1 one 裏的 jmeter一直是一款很好的接口和性能測試工具,它是開源的,不需要為此支付任何費用,而且可以下載源碼,可以在修改源代碼並在此基礎上拓展自己的功能或插件,它可以跟ant和jenkins結合起來搭建自己的自動化
Spring中整合Cage,實現驗證碼功能
ger 類型 body match exce sub pom esp rec 1.pom.xml中添加Cage依賴。
<dependency>
<groupId>com.github.cage</groupId
從零實現一個http服務器
retrieve vba ilove ext TP 應用場景 註釋 end HA 我始終覺得,天生的出身很重要,但後天的努力更加重要,所以如今的很多“科班”往往不如後天努力的“非科班”。所以,我們需要重新給“專業”和“專家”下一個定義:所謂專業,就是別人搞你不搞,這就是你的
Python實現簡單HTTP服務器(一)
recv ati listen bind ESS 內容 text code 讀取內容 一.返回固定內容
# coding:utf-8
import socket
from multiprocessing import Process
def handle_clien
Python 進行 SSH 操作,實現本地與服務器的鏈接,進行文件的上傳和下載
enc 項目介紹 use 解讀 數據庫文件 需要 toad 鏈接 {} Python 進行 SSH 操作,實現本地與服務器的鏈接,進行文件的上傳和下載
2018年5月26日 19:03 閱讀 375 評論 7
我本地和服務器的連接一直使用的是 Xshell 5,
Linux6.5中配置PXE自動裝機,實現批量裝機服務。
linu type 大量 oss 9.png tex 技術 批量裝機 watermark 為了增加工作效率,我們在進行linux裝機時,在面臨大量裸機的情況下,
PXE自動裝機的作用尤為顯著,能夠大大減少我們工作壓力,增加工作效率。
安裝環境:linux6.5一臺,w
springboot2整合easypoi,實現Excel匯入匯出
1.新增Maven依賴
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<v
Springboot整合curator,實現分散式鎖(zookeeper)
0.linux安裝啟動zookeeper
yum install nc
wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz
tar -zxvf zookeepe
node+mysql+ajax+javascript搭建一套服務介面,實現前後臺數據請求
node+mysql+ajax+javascript搭建一套服務介面,實現前後臺數據請求
效果圖如下所示:
啟動服務
get請求
查詢mysql資料庫
express介紹
Express 基於
SSM整合Shiro,實現系統的認證管理和許可權管理?
資料:
一、首先匯入依賴:
<!--spring的版本號-->
<spring-version>4.3.13.RELEASE</spring-version>
<!--mybatis的版本號
springboot整合redis,實現session共享
一直對serssion的共享有著很大的疑惑,對於我現在的工作的地方,所在的部門,因為沒有前臺頁面,純屬後臺。所以,不會存在session的共享問題。但是出於好奇,也是心裡的疑惑,今天也動手實驗了下。
SpringBoot整合RabbitMQ,實現訊息傳送和消費
下載安裝Erlang和RabbitMQ
Erlang和RabbitMQ:https://www.cnblogs.com/theRhyme/p/10069611.html
專案建立和依賴
推薦SpringCloud專案線上建立:https://start.spring.io/
不用上面這
spring mvc攔截器,實現統計http請求的後臺執行時間
使用兩種方式,實現攔截http請求的後臺執行時間。
廢話不多說直接上程式碼
/**
* Http請求時間統計
* 攔截所有請求
*/
public class HttpRquestTimeInterceptor extends HandlerInterceptorAdapter {
Threa