Netty设置为Https访问
SSLContextFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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; } } |
处理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
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依赖的包
1
2
3
4
5
|
< dependency > < groupId >io.netty</ groupId > < artifactId >netty-all</ artifactId > < version >4.1.27.Final</ version > </ dependency > |
1.netty启动入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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请求、处理、返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
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,调用本地接口。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://zhaozhen.blog.csdn.net/article/details/83352819