【Java教程】Netty如何设置为Https访问详解

所需工具:

Java

聪明的大脑

勤劳的双手

 

注意:本站只提供教程,不提供任何成品+工具+软件链接,仅限用于学习和研究,禁止商业用途,未经允许禁止转载/分享等

 

教程如下

Netty设置为Https访问

SSLContextFactory

 	public 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<String, String> 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<String, String> 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依赖的包

 	<dependency>
 	     <groupId>io.netty</groupId>
 	     <artifactId>netty-all</artifactId>
 	     <version>4.1.27.Final</version>
 	</dependency>

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.编写NettyHttpServer

 	package 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<FullHttpRequest>
 	{
 	
 	     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<String, String> 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<String, String> getRequestParams(ChannelHandlerContext ctx, HttpRequest req)
 	     {
 	     Map<String, String> requestParams = new HashMap<String, String>();
 	     // 处理get请求
 	     if (req.method() == HttpMethod.GET)
 	     {
 	     QueryStringDecoder decoder = new QueryStringDecoder(req.uri());
 	     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.method() == 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;
 	     }
 	}

启来后,使用postman,调用本地接口。

标签

发表评论

评论列表(1)