2022-06-06 12:09:09 来源 : 软件开发网
Netty设置为Https访问
SSLContextFactory
处理类
Netty实现Http协议
maven依赖的包
1.netty启动入口
2.编写NettyHttpServer
3.处理http请求、处理、返回
Netty设置为Https访问SSLContextFactorypublic class SSLContextFactory { public static SSLContext getSslContext() throws Exception { char[] passArray = "zhuofansoft".toCharArray(); SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); KeyStore ks = KeyStore.getInstance("JKS"); //鍔犺浇keytool 鐢熸垚鐨勬枃浠� FileInputStream inputStream = new FileInputStream("D://server.keystore"); ks.load(inputStream, passArray); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ks, passArray); sslContext.init(kmf.getKeyManagers(), null, null); inputStream.close(); return sslContext; }}
处理类public class HttpsSeverHandler extends ChannelInboundHandlerAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(HttpServerHandler.class); @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof HttpRequest) { HttpRequest request = (HttpRequest) msg; LOGGER.info("access messageReceived invoke success.."); Long startTime = System.currentTimeMillis(); // 400 if (!request.decoderResult().isSuccess()) { sendError(ctx, HttpResponseStatus.BAD_REQUEST); return; } // 405 if (request.method() != GET) { sendError(ctx, HttpResponseStatus.METHOD_NOT_ALLOWED); return; } FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.OK); Map parmMap = new RequestParser((FullHttpRequest) request).parse(); //jQuery跨域携带标识符 String callback = parmMap.get("callback"); LOGGER.info("connection jsonp header:[{}],request param:[{}]",callback,parmMap.get("requestParam"));; //请求参数 DeviceRequest deviceRequest = JSONObject.parseObject(parmMap.get("requestParam"), DeviceRequest.class); DeviceResultWapper> result = getClientResponse(deviceRequest); LOGGER.info("get client response success.. response:[{}]",JSONObject.toJSONString(result)); LOGGER.info("get client response take time:[{}]",(System.currentTimeMillis()-startTime)/1000+"s"); String content = callback + "("+JSONObject.toJSONString(result)+")"; byte[] bs = content.getBytes("UTF-8"); response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(bs.length)); response.content().writeBytes(ByteBuffer.wrap(bs)); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);/* HttpRequest request = (HttpRequest) msg; boolean keepaLive = HttpUtil.isKeepAlive(request); System.out.println("method" + request.method()); System.out.println("uri" + request.uri()); FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); httpResponse.content().writeBytes("https".getBytes()); httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8"); httpResponse.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().readableBytes()); if (keepaLive) { httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); ctx.writeAndFlush(httpResponse); } else { ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE); }*/ } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); if (ctx.channel().isActive()) { sendError(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR); } } private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) { FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status, Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8)); response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8"); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); }/* @Override protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { LOGGER.info("access messageReceived invoke success.."); Long startTime = System.currentTimeMillis(); // 400 if (!request.decoderResult().isSuccess()) { sendError(ctx, HttpResponseStatus.BAD_REQUEST); return; } // 405 if (request.method() != GET) { sendError(ctx, HttpResponseStatus.METHOD_NOT_ALLOWED); return; } FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.OK); Map parmMap = new RequestParser(request).parse(); //jQuery跨域携带标识符 String callback = parmMap.get("callback"); LOGGER.info("connection jsonp header:[{}],request param:[{}]",callback,parmMap.get("requestParam"));; //请求参数 DeviceRequest deviceRequest = JSONObject.parseObject(parmMap.get("requestParam"), DeviceRequest.class); DeviceResultWapper> result = getClientResponse(deviceRequest); LOGGER.info("get client response success.. response:[{}]",JSONObject.toJSONString(result)); LOGGER.info("get client response take time:[{}]",(System.currentTimeMillis()-startTime)/1000+"s"); String content = callback + "("+JSONObject.toJSONString(result)+")"; byte[] bs = content.getBytes("UTF-8"); response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(bs.length)); response.content().writeBytes(ByteBuffer.wrap(bs)); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); }*/ private DeviceResultWapper> getClientResponse(DeviceRequest deviceRequest) { // 拼接参数 DeviceCommandVo deviceCommandVo = DeviceType.wapperRequestParam(deviceRequest); if (deviceCommandVo == null) { return DeviceResultWapper.fail(400, "remote user with illegal param"); } SerialPortOrder serialPortOrder = DeviceOrderFactory.produce(deviceCommandVo.getDeviceTypeId()); return serialPortOrder.order(deviceCommandVo); }}
Netty实现Http协议这里简单介绍下,项目中使用netty在main方法中启动项目,实现http协议。
maven依赖的包 io.netty netty-all 4.1.27.Final
1.netty启动入口package com.fotile.cloud.ruleengin;import javax.servlet.ServletException;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.fotile.cloud.ruleengin.falsework.NettyHttpServer;/** * Hello world! * */public class RuleApplication{ // 引擎端口 private final static int ENGINE_PORT = 8086; /** * http prot is 8085, */ public static void main(String[] args) {// 加载spring配置ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");DispatcherServlet servlet = getDispatcherServlet(ctx);NettyHttpServer server = new NettyHttpServer(ENGINE_PORT, servlet);server.start(); } public static DispatcherServlet getDispatcherServlet(ApplicationContext ctx) {XmlWebApplicationContext mvcContext = new XmlWebApplicationContext();// 加载spring-mvc配置mvcContext.setConfigLocation("classpath:spring-mvc.xml");mvcContext.setParent(ctx);MockServletConfig servletConfig = new MockServletConfig(mvcContext.getServletContext(), "dispatcherServlet");DispatcherServlet dispatcherServlet = new DispatcherServlet(mvcContext);try{ dispatcherServlet.init(servletConfig);} catch (ServletException e){ e.printStackTrace();}return dispatcherServlet; }}
2.编写NettyHttpServerpackage com.fotile.cloud.openplatform.falsework;import org.apache.log4j.Logger;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;public class NettyHttpServer implements Runnable{ private Logger LOGGER = Logger.getLogger(this.getClass()); private int port; private DispatcherServlet servlet; 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); LOGGER.info("NettyHttpServer Run successfully"); // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(port).sync(); // 等待服务器 socket 关闭 。在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。 f.channel().closeFuture().sync();} catch (Exception e){ System.out.println("NettySever start fail" + e);} finally{ workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully();} } @Override public void run() {start(); }}
3.处理http请求、处理、返回package com.fotile.cloud.ruleengin.falsework;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 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.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{ private DispatcherServlet servlet; public HttpRequestHandler(DispatcherServlet servlet) {this.servlet = servlet; } @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {boolean flag = HttpMethod.POST.equals(fullHttpRequest.method())|| HttpMethod.GET.equals(fullHttpRequest.method()) || HttpMethod.DELETE.equals(fullHttpRequest.method())|| HttpMethod.PUT.equals(fullHttpRequest.method());Map parammap = getRequestParams(ctx, fullHttpRequest);if (flag && ctx.channel().isActive()){ // HTTP请求、GET/POST MockHttpServletResponse servletResponse = new MockHttpServletResponse(); MockHttpServletRequest servletRequest = new MockHttpServletRequest( servlet.getServletConfig().getServletContext()); // headers for (String name : fullHttpRequest.headers().names()) {for (String value : fullHttpRequest.headers().getAll(name)){ servletRequest.addHeader(name, value);} } String uri = fullHttpRequest.uri(); 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.method().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); if (uriComponents.getQuery() != null) {String query = UriUtils.decode(uriComponents.getQuery(), "UTF-8");servletRequest.setQueryString(query); } if (parammap != null && parammap.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"));} } servlet.service(servletRequest, servletResponse); HttpResponseStatus status = HttpResponseStatus.valueOf(servletResponse.getStatus()); String result = servletResponse.getContentAsString(); result = StringUtils.isEmpty(result) ? status.toString() : 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 getRequestParams(ChannelHandlerContext ctx, HttpRequest req) {Map requestParams = new HashMap();// 处理get请求if (req.method() == HttpMethod.GET){ QueryStringDecoder decoder = new QueryStringDecoder(req.uri()); Map> parame = decoder.parameters(); Iterator>> iterator = parame.entrySet().iterator(); while (iterator.hasNext()) {Entry> next = iterator.next();requestParams.put(next.getKey(), next.getValue().get(0)); }}// 处理POST请求if (req.method() == HttpMethod.POST){ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), req); List postData = decoder.getBodyHttpDatas(); // for (InterfaceHttpData data : postData) {if (data.getHttpDataType() == HttpDataType.Attribute){ MemoryAttribute attribute = (MemoryAttribute) data; requestParams.put(attribute.getName(), attribute.getValue());} }}return requestParams; } }
启来后,使用postman,调用本地接口。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持软件开发网。