Netty如何設(shè)置為Https訪問(wèn)
Netty設(shè)置為Https訪問(wèn)
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跨域攜帶標(biāo)識(shí)符 String callback = parmMap.get("callback"); LOGGER.info("connection jsonp header:[{}],request param:[{}]",callback,parmMap.get("requestParam"));; //請(qǐng)求參數(shù) 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跨域攜帶標(biāo)識(shí)符 String callback = parmMap.get("callback"); LOGGER.info("connection jsonp header:[{}],request param:[{}]",callback,parmMap.get("requestParam"));; //請(qǐng)求參數(shù) 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) { // 拼接參數(shù) 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實(shí)現(xiàn)Http協(xié)議
這里簡(jiǎn)單介紹下,項(xiàng)目中使用netty在main方法中啟動(dòng)項(xiàng)目,實(shí)現(xiàn)http協(xié)議。
maven依賴的包
<dependency> ?? ?<groupId>io.netty</groupId> ?? ?<artifactId>netty-all</artifactId> ?? ?<version>4.1.27.Final</version> </dependency>
1.netty啟動(dòng)入口
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"); // 綁定端口,開(kāi)始接收進(jìn)來(lái)的連接 ChannelFuture f = b.bind(port).sync(); // 等待服務(wù)器 socket 關(guān)閉 。在這個(gè)例子中,這不會(huì)發(fā)生,但你可以優(yōu)雅地關(guān)閉你的服務(wù)器。 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請(qǐng)求、處理、返回
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請(qǐng)求、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請(qǐng)求、get請(qǐng)求的參數(shù)保存到map中 */ private Map<String, String> getRequestParams(ChannelHandlerContext ctx, HttpRequest req) { Map<String, String> requestParams = new HashMap<String, String>(); // 處理get請(qǐng)求 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請(qǐng)求 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; } }
啟來(lái)后,使用postman,調(diào)用本地接口。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring?Boot?教程之創(chuàng)建項(xiàng)目的三種方式
這篇文章主要分享了Spring?Boot?教程之創(chuàng)建項(xiàng)目的三種方式,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05java二進(jìn)制運(yùn)算基礎(chǔ)知識(shí)點(diǎn)詳解
在本文里小編給大家分享了關(guān)于java二進(jìn)制運(yùn)算基礎(chǔ)知識(shí)點(diǎn)以及實(shí)例代碼內(nèi)容,需要的朋友們參考學(xué)習(xí)下。2019-08-08Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法
這篇文章主要介紹了Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12Android開(kāi)發(fā)中實(shí)現(xiàn)用戶注冊(cè)和登陸的代碼實(shí)例分享
這篇文章主要介紹了Android開(kāi)發(fā)中實(shí)現(xiàn)用戶注冊(cè)和登陸的代碼實(shí)例分享,只是實(shí)現(xiàn)基本功能,界面華麗度就請(qǐng)忽略啦XD 需要的朋友可以參考下2015-12-12